Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/wrtsh/wrtsh1.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/XPropertySet.hpp>
21
#include <com/sun/star/container/XChild.hpp>
22
#include <com/sun/star/embed/EmbedMisc.hpp>
23
#include <com/sun/star/embed/EmbedStates.hpp>
24
#include <com/sun/star/embed/EmbedVerbs.hpp>
25
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
26
#include <com/sun/star/chart2/XChartDocument.hpp>
27
#include <com/sun/star/util/XModifiable.hpp>
28
#include <com/sun/star/lang/XInitialization.hpp>
29
30
#include <hintids.hxx>
31
#include <sot/exchange.hxx>
32
#include <svx/xfillit0.hxx>
33
#include <svx/hdft.hxx>
34
#include <svx/svdview.hxx>
35
#include <svl/itemiter.hxx>
36
#include <tools/bigint.hxx>
37
#include <svtools/insdlg.hxx>
38
#include <sfx2/ipclient.hxx>
39
#include <editeng/editeng.hxx>
40
#include <editeng/editobj.hxx>
41
#include <editeng/formatbreakitem.hxx>
42
#include <editeng/svxacorr.hxx>
43
#include <editeng/ulspitem.hxx>
44
#include <vcl/graph.hxx>
45
#include <unotools/charclass.hxx>
46
#include <comphelper/storagehelper.hxx>
47
#include <comphelper/random.hxx>
48
#include <svx/svxdlg.hxx>
49
#include <svx/extrusionbar.hxx>
50
#include <svx/fontworkbar.hxx>
51
#include <dialoghelp.hxx>
52
#include <frmfmt.hxx>
53
#include <fmtftn.hxx>
54
#include <fmthdft.hxx>
55
#include <fmtpdsc.hxx>
56
#include <txtfrm.hxx>
57
#include <wdocsh.hxx>
58
#include <swmodule.hxx>
59
#include <wrtsh.hxx>
60
#include <view.hxx>
61
#include <cmdid.h>
62
#include <pagedesc.hxx>
63
#include <frmmgr.hxx>
64
#include <swundo.hxx>
65
#include <swcli.hxx>
66
#include <poolfmt.hxx>
67
#include <postithelper.hxx>
68
#include <edtwin.hxx>
69
#include <fmtcol.hxx>
70
#include <swtable.hxx>
71
#include <viscrs.hxx>
72
#include <swdtflvr.hxx>
73
#include <doc.hxx>
74
#include <IDocumentSettingAccess.hxx>
75
#include <SwCapObjType.hxx>
76
#include <SwStyleNameMapper.hxx>
77
#include <sfx2/request.hxx>
78
#include <paratr.hxx>
79
#include <ndtxt.hxx>
80
#include <editeng/acorrcfg.hxx>
81
#include <IMark.hxx>
82
#include <sfx2/bindings.hxx>
83
#include <flyfrm.hxx>
84
85
// -> #111827#
86
#include <SwRewriter.hxx>
87
#include <strings.hrc>
88
// <- #111827#
89
90
#include <toolkit/helper/vclunohelper.hxx>
91
#include <sfx2/viewfrm.hxx>
92
#include <vcl/uitest/logger.hxx>
93
#include <vcl/uitest/eventdescription.hxx>
94
#include <osl/diagnose.h>
95
#include <o3tl/unit_conversion.hxx>
96
#include <officecfg/Office/Common.hxx>
97
98
#include <PostItMgr.hxx>
99
#include <FrameControlsManager.hxx>
100
#include <fldmgr.hxx>
101
#include <docufld.hxx>
102
#include <IDocumentFieldsAccess.hxx>
103
#include <fmtfld.hxx>
104
105
#include <sfx2/msgpool.hxx>
106
#include <sfx2/msg.hxx>
107
#include <svtools/embedhlp.hxx>
108
#include <svtools/strings.hrc>
109
#include <svtools/svtresid.hxx>
110
#include <svx/postattr.hxx>
111
#include <comphelper/lok.hxx>
112
#include <comphelper/propertyvalue.hxx>
113
#include <svtools/optionsdrawinglayer.hxx>
114
#include <svl/numformat.hxx>
115
#include <svl/zformat.hxx>
116
#include <vcl/weld/MessageDialog.hxx>
117
#include <memory>
118
119
#include "../../core/crsr/callnk.hxx"
120
#include <frmtool.hxx>
121
#include <viewopt.hxx>
122
123
#include <IDocumentRedlineAccess.hxx>
124
#include <IDocumentUndoRedo.hxx>
125
#include <UndoInsert.hxx>
126
#include <UndoCore.hxx>
127
#include <formatlinebreak.hxx>
128
#include <formatcontentcontrol.hxx>
129
#include <textcontentcontrol.hxx>
130
131
#include <UndoAttribute.hxx>
132
133
#include <comphelper/flagguard.hxx>
134
135
using namespace sw::mark;
136
using namespace com::sun::star;
137
namespace {
138
139
void collectUIInformation(const OUString& rAction, const OUString& aParameters)
140
0
{
141
0
    EventDescription aDescription;
142
0
    aDescription.aAction = rAction;
143
0
    aDescription.aParameters = {{"parameters", aParameters}};
144
0
    aDescription.aID = "writer_edit";
145
0
    aDescription.aKeyWord = "SwEditWinUIObject";
146
0
    aDescription.aParent = "MainWindow";
147
0
    UITestLogger::getInstance().logEvent(aDescription);
148
0
}
149
150
}
151
152
sal_uInt32 MakeAllOutlineContentTemporarilyVisible::nLock = 0;
153
154
static bool lcl_IsAllowed(const SwWrtShell* rSh)
155
0
{
156
0
    if (rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton() && rSh->IsEndPara())
157
0
    {
158
0
        SwTextNode* pTextNode = rSh->GetCursor()->GetPointNode().GetTextNode();
159
0
        if (pTextNode && pTextNode->IsOutline())
160
0
        {
161
            // disallow if this is an outline node having folded content
162
0
            if (!pTextNode->GetAttrOutlineContentVisible())
163
0
                return false;
164
0
        }
165
0
    }
166
0
    return true;
167
0
}
168
169
#define BITFLD_INI_LIST \
170
3.28k
        m_bClearMark = \
171
3.28k
        m_bIns = true;\
172
3.28k
        m_bAddMode = \
173
3.28k
        m_bBlockMode = \
174
3.28k
        m_bExtMode = \
175
3.28k
        m_bInSelect = \
176
3.28k
        m_bLayoutMode = \
177
3.28k
        m_bSelWrd = \
178
3.28k
        m_bSelLn = \
179
3.28k
        m_bRetainSelection = false; \
180
3.28k
        m_bIsInClickToEdit = false;
181
182
static SvxAutoCorrect* lcl_IsAutoCorr()
183
0
{
184
0
    SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
185
0
    if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
186
0
                            ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL |
187
0
                            ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect |
188
0
                            ACFlags::SetDOIAttr ))
189
0
        pACorr = nullptr;
190
0
    return pACorr;
191
0
}
192
193
void SwWrtShell::NoEdit(bool bHideCursor)
194
0
{
195
0
    if(bHideCursor)
196
0
        HideCursor();
197
0
}
198
199
void SwWrtShell::Edit()
200
0
{
201
0
    if (CanInsert())
202
0
    {
203
0
        ShowCursor();
204
0
    }
205
0
}
206
207
bool SwWrtShell::IsEndWrd()
208
0
{
209
0
    SwMvContext aMvContext(this);
210
0
    if(IsEndPara() && !IsSttPara())
211
0
        return true;
212
213
0
    return IsEndWord();
214
0
}
215
216
// Insert string
217
void SwWrtShell::InsertByWord( const OUString & rStr)
218
0
{
219
0
    if( rStr.isEmpty() )
220
0
        return;
221
222
0
    bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
223
0
    sal_Int32 nPos = 0, nStt = 0;
224
0
    for( ; nPos < rStr.getLength(); nPos++ )
225
0
    {
226
0
        bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
227
0
        if( bTmpDelim != bDelim )
228
0
        {
229
0
            Insert( rStr.copy( nStt, nPos - nStt ));
230
0
            nStt = nPos;
231
0
        }
232
0
    }
233
0
    if( nStt != nPos )
234
0
        Insert( rStr.copy( nStt, nPos - nStt ));
235
0
}
236
237
void SwWrtShell::Insert( const OUString &rStr )
238
0
{
239
0
    ResetCursorStack();
240
0
    if( !CanInsert() )
241
0
        return;
242
243
0
    bool bStarted = false;
244
0
    bool bHasSel = HasSelection(),
245
0
         bCallIns = m_bIns /*|| bHasSel*/;
246
0
    bool bDeleted = false;
247
248
0
    if( bHasSel || ( !m_bIns && IsInHiddenRange(/*bSelect=*/true) ) )
249
0
    {
250
            // Only here parenthesizing, because the normal
251
            // insert is already in parentheses at Editshell.
252
0
        StartAllAction();
253
254
0
        SwRewriter aRewriter;
255
256
0
        aRewriter.AddRule(UndoArg1, GetCursorDescr());
257
0
        aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
258
0
        {
259
0
            OUString aTmpStr = SwResId(STR_START_QUOTE) +
260
0
                rStr + SwResId(STR_END_QUOTE);
261
262
0
            aRewriter.AddRule(UndoArg3, aTmpStr);
263
0
        }
264
265
0
        StartUndo(SwUndoId::REPLACE, &aRewriter);
266
0
        bStarted = true;
267
0
        Push();
268
        // let's interpret a selection within the same node as "replace"
269
0
        bDeleted = DelRight(GetCursor()->GetPoint()->GetNode() == GetCursor()->GetMark()->GetNode());
270
0
        Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore selection (if tracking changes)
271
0
        NormalizePam(false); // tdf#127635 put point at the end of deletion
272
0
        ClearMark();
273
0
    }
274
275
0
    bCallIns ?
276
0
        SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
277
278
    // Check whether node is content control
279
0
    SwTextContentControl* pTextContentControl = CursorInsideContentControl();
280
0
    if (pTextContentControl)
281
0
    {
282
0
        std::shared_ptr<SwContentControl> pContentControl =
283
0
            pTextContentControl->GetContentControl().GetContentControl();
284
0
        if (pContentControl)
285
0
        {
286
            // Set showingPlcHdr to false as node has been edited
287
0
            pContentControl->SetShowingPlaceHolder(false);
288
0
        }
289
0
    }
290
291
0
    if( bStarted )
292
0
    {
293
0
        EndUndo();
294
0
        EndAllAction();
295
0
    }
296
0
}
297
298
// Maximum height limit not possible, because the maximum height
299
// of the current frame can not be obtained.
300
301
void SwWrtShell::InsertGraphic( const OUString &rPath, const OUString &rFilter,
302
                                const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
303
                                RndStdIds nAnchorType )
304
0
{
305
0
    ResetCursorStack();
306
0
    if ( !CanInsert() )
307
0
        return;
308
309
0
    StartAllAction();
310
311
0
    SwRewriter aRewriter;
312
0
    aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC));
313
314
0
    StartUndo(SwUndoId::INSERT, &aRewriter);
315
316
0
    if ( HasSelection() )
317
0
        DelRight();
318
        // Inserted graphics in its own paragraph,
319
        // if at the end of a non-empty paragraph.
320
    //For i120928,avoid to split node
321
322
0
    EnterSelFrameMode();
323
324
0
    bool bSetGrfSize = true;
325
0
    bool bOwnMgr     = false;
326
327
0
    if ( !pFrameMgr )
328
0
    {
329
0
        bOwnMgr = true;
330
0
        pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF, nullptr );
331
332
        // CAUTION
333
        // GetAttrSet makes an adjustment
334
        // While pasting is a SwFrameSize present
335
        // because of the DEF-Framesize
336
        // These must be removed explicitly for the optimal size.
337
0
        pFrameMgr->DelAttr(RES_FRM_SIZE);
338
339
0
        if (nAnchorType != RndStdIds::FLY_AT_PARA)
340
            // Something other than at-para was requested.
341
0
            pFrameMgr->SetAnchor(nAnchorType);
342
0
    }
343
0
    else
344
0
    {
345
0
        Size aSz( pFrameMgr->GetSize() );
346
0
        if ( !aSz.Width() || !aSz.Height() )
347
0
        {
348
0
            aSz.setWidth(o3tl::toTwips(1, o3tl::Length::cm));
349
0
            aSz.setHeight(o3tl::toTwips(1, o3tl::Length::cm));
350
0
            pFrameMgr->SetSize( aSz );
351
0
        }
352
0
        else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
353
0
            bSetGrfSize = false;
354
355
0
        pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed);
356
0
    }
357
358
    // during change tracking, insert the image anchored as character
359
    // (to create an SwRangeRedline on its anchor point)
360
0
    if ( IsRedlineOn() && nAnchorType != RndStdIds::FLY_AS_CHAR )
361
0
        pFrameMgr->SetAnchor( RndStdIds::FLY_AS_CHAR );
362
363
    // Insert the graphic
364
0
    SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
365
0
    if ( bOwnMgr )
366
0
        pFrameMgr->UpdateAttrMgr();
367
368
0
    if( bSetGrfSize )
369
0
    {
370
0
        Size aSizePixel = rGrf.GetSizePixel();
371
0
        Size aBound = GetGraphicDefaultSize();
372
373
0
        sal_Int32 nPreferredDPI = mxDoc->getIDocumentSettingAccess().getImagePreferredDPI();
374
0
        Size aGrfSize;
375
376
0
        if (nPreferredDPI > 0)
377
0
        {
378
0
            auto nWidth = o3tl::toTwips(aSizePixel.Width() / double(nPreferredDPI), o3tl::Length::in);
379
0
            auto nHeight = o3tl::toTwips(aSizePixel.Height() / double(nPreferredDPI), o3tl::Length::in);
380
0
            aGrfSize = Size(nWidth, nHeight);
381
0
        }
382
0
        else
383
0
        {
384
0
            GetGrfSize(aGrfSize);
385
0
        }
386
387
        // Add the margin attributes to GrfSize,
388
        // because these counts at the margin additionally
389
0
        aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
390
0
        aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
391
392
0
        const BigInt aTempWidth( aGrfSize.Width() );
393
0
        const BigInt aTempHeight( aGrfSize.Height());
394
395
        // Fit width if necessary, scale down the height proportional thereafter.
396
0
        if( aGrfSize.Width() > aBound.Width() )
397
0
        {
398
0
            aGrfSize.setWidth( aBound.Width() );
399
0
            aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
400
0
        }
401
        // Fit height if necessary, scale down the width proportional thereafter.
402
0
        if( aGrfSize.Height() > aBound.Height() )
403
0
        {
404
0
            aGrfSize.setHeight( aBound.Height() );
405
0
            aGrfSize.setWidth(  BigInt(aBound.Height()) * aTempWidth / aTempHeight );
406
0
        }
407
0
        pFrameMgr->SetSize( aGrfSize );
408
0
        pFrameMgr->UpdateFlyFrame();
409
0
    }
410
0
    if ( bOwnMgr )
411
0
        delete pFrameMgr;
412
413
0
    EndUndo();
414
0
    EndAllAction();
415
0
}
416
417
// Insert an OLE-Object into the CORE.
418
// if no object is transferred, then one will be created.
419
420
void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
421
                               sal_uInt16 nSlotId )
422
0
{
423
0
    ResetCursorStack();
424
0
    if( !CanInsert() )
425
0
        return;
426
427
0
    if( !xRef.is() )
428
0
    {
429
        // temporary storage
430
0
        svt::EmbeddedObjectRef xObj;
431
0
        uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
432
0
        bool bDoVerb = true;
433
0
        if ( pName )
434
0
        {
435
0
            comphelper::EmbeddedObjectContainer aCnt( xStor );
436
0
            OUString aName;
437
            // TODO/LATER: get aspect?
438
0
            xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
439
0
        }
440
0
        else
441
0
        {
442
0
            SvObjectServerList aServerList;
443
0
            switch (nSlotId)
444
0
            {
445
0
                case SID_INSERT_OBJECT:
446
0
                {
447
0
                    if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
448
0
                    {
449
0
                        std::unique_ptr<weld::MessageDialog> xError(
450
0
                            Application::CreateMessageDialog(
451
0
                                nullptr, VclMessageType::Warning, VclButtonsType::Ok,
452
0
                                SvtResId(STR_WARNING_ACTIVE_CONTENT_DISABLED)));
453
0
                        xError->run();
454
0
                        break;
455
0
                    }
456
0
                    aServerList.FillInsertObjects();
457
0
                    aServerList.Remove( SwDocShell::Factory().GetClassId() );
458
0
                    [[fallthrough]];
459
0
                }
460
461
                // TODO/LATER: recording! Convert properties to items
462
0
                case SID_INSERT_FLOATINGFRAME:
463
0
                {
464
0
                    SfxSlotPool* pSlotPool = SwModule::get()->GetSlotPool();
465
0
                    const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
466
0
                    OUString aCmd = pSlot->GetCommand();
467
0
                    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
468
0
                    ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()),
469
0
                                aCmd, xStor, &aServerList));
470
0
                    if (pDlg)
471
0
                    {
472
0
                        pDlg->Execute();
473
0
                        bDoVerb = pDlg->IsCreateNew();
474
0
                        OUString aIconMediaType;
475
0
                        uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
476
0
                        xObj.Assign( pDlg->GetObject(),
477
0
                                     xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
478
0
                        if ( xIconMetaFile.is() )
479
0
                            xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
480
0
                    }
481
482
0
                    break;
483
0
                }
484
485
0
                default:
486
0
                    break;
487
0
            }
488
0
        }
489
490
0
        if ( xObj.is() )
491
0
        {
492
0
            if( InsertOleObject( xObj ) && bDoVerb )
493
0
            {
494
0
                SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
495
0
                if ( !pClient )
496
0
                {
497
0
                    pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
498
0
                    SetCheckForOLEInCaption( true );
499
0
                }
500
501
0
                if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
502
0
                {
503
0
                    SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
504
0
                    aArea += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
505
0
                    MapMode aMapMode( MapUnit::MapTwip );
506
0
                    Size aSize = xObj.GetSize( &aMapMode );
507
0
                    aArea.Width( aSize.Width() );
508
0
                    aArea.Height( aSize.Height() );
509
0
                    RequestObjectResize( aArea, xObj.GetObject() );
510
0
                }
511
0
                else
512
0
                    CalcAndSetScale( xObj );
513
514
                //#50270# We don't need to handle error, this is handled by the
515
                //DoVerb in the SfxViewShell
516
0
                pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
517
518
                // TODO/LATER: set document name - should be done in Client
519
0
            }
520
0
        }
521
0
    }
522
0
    else
523
0
    {
524
0
        if( HasSelection() )
525
0
            DelRight();
526
0
        InsertOleObject( xRef );
527
0
    }
528
0
}
529
530
// Insert object into the Core.
531
// From ClipBoard or Insert
532
533
bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
534
0
{
535
    //tdf#125100 Ensure that ole object is initially shown as pictogram
536
0
    comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mxDoc->GetDocShell()->getEmbeddedObjectContainer();
537
0
    bool bSaveUserAllowsLinkUpdate = rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
538
0
    rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true);
539
540
0
    ResetCursorStack();
541
0
    StartAllAction();
542
543
0
    StartUndo(SwUndoId::INSERT);
544
545
    //Some differences between StarMath and any other objects:
546
    //1. Selections should be deleted. For StarMath the Text should be
547
    //   passed to the Object
548
    //2. If the cursor is at the end of a non empty paragraph a paragraph
549
    //   break should be inserted. StarMath objects are character bound and
550
    //   no break should be inserted.
551
    //3. If an selection is passed to a StarMath object, this object should
552
    //   not be activated. false should be returned then.
553
0
    bool bStarMath = true;
554
0
    bool bActivate = true;
555
556
    // set parent to get correct VisArea(in case of object needing parent printer)
557
0
    uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
558
0
    if ( xChild.is() )
559
0
        xChild->setParent( mxDoc->GetDocShell()->GetModel() );
560
561
0
    SvGlobalName aCLSID( xRef->getClassID() );
562
0
    bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
563
0
    if( IsSelection() )
564
0
    {
565
0
        if( bStarMath )
566
0
        {
567
0
            OUString aMathData;
568
0
            GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
569
570
0
            if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
571
0
            {
572
0
                uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
573
0
                if ( xSet.is() )
574
0
                {
575
0
                    try
576
0
                    {
577
0
                        xSet->setPropertyValue(u"Formula"_ustr, uno::Any( aMathData ) );
578
0
                        bActivate = false;
579
0
                    }
580
0
                    catch (const uno::Exception&)
581
0
                    {
582
0
                    }
583
0
                }
584
0
            }
585
0
        }
586
0
        DelRight();
587
0
    }
588
589
0
    if ( !bStarMath )
590
0
        SwFEShell::SplitNode(false);
591
592
0
    EnterSelFrameMode();
593
594
0
    const SvGlobalName* pName = nullptr;
595
0
    SvGlobalName aObjClsId;
596
0
    if (xRef.is())
597
0
    {
598
0
        aObjClsId = SvGlobalName(xRef.GetObject()->getClassID());
599
0
        pName = &aObjClsId;
600
0
    }
601
0
    SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE, pName );
602
0
    aFrameMgr.SetHeightSizeType(SwFrameSize::Fixed);
603
604
0
    SwRect aBound;
605
0
    CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
606
607
    //The Size should be suggested by the OLE server
608
0
    MapMode aMapMode( MapUnit::MapTwip );
609
0
    Size aSz = xRef.GetSize( &aMapMode );
610
611
    //Object size can be limited
612
0
    if ( aSz.Width() > aBound.Width() )
613
0
    {
614
        //Always limit proportional.
615
0
        aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
616
0
        aSz.setWidth( aBound.Width() );
617
0
    }
618
0
    aFrameMgr.SetSize( aSz );
619
0
    SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
620
621
    // --> #i972#
622
0
    if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
623
0
        AlignFormulaToBaseline( xRef.GetObject() );
624
625
0
    if (pFlyFrameFormat)
626
0
        *pFlyFrameFormat = pFormat;
627
628
0
    if ( SotExchange::IsChart( aCLSID ) )
629
0
    {
630
0
        const uno::Reference< embed::XEmbeddedObject >& xEmbeddedObj = xRef.GetObject();
631
0
        if ( xEmbeddedObj.is() )
632
0
        {
633
0
            bool bDisableDataTableDialog = false;
634
0
            svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
635
0
            uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
636
0
            if ( xProps.is() &&
637
0
                 ( xProps->getPropertyValue(u"DisableDataTableDialog"_ustr) >>= bDisableDataTableDialog ) &&
638
0
                 bDisableDataTableDialog )
639
0
            {
640
0
                xProps->setPropertyValue(u"DisableDataTableDialog"_ustr,
641
0
                    uno::Any( false ) );
642
0
                xProps->setPropertyValue(u"DisableComplexChartTypes"_ustr,
643
0
                    uno::Any( false ) );
644
0
                uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
645
0
                if ( xModifiable.is() )
646
0
                {
647
0
                    xModifiable->setModified( true );
648
0
                }
649
0
            }
650
0
        }
651
0
    }
652
653
0
    EndAllAction();
654
0
    GetView().AutoCaption(OLE_CAP, &aCLSID);
655
656
0
    SwRewriter aRewriter;
657
658
0
    if ( bStarMath )
659
0
        aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULA));
660
0
    else if ( SotExchange::IsChart( aCLSID ) )
661
0
        aRewriter.AddRule(UndoArg1, SwResId(STR_CHART));
662
0
    else
663
0
        aRewriter.AddRule(UndoArg1, SwResId(STR_OLE));
664
665
0
    EndUndo(SwUndoId::INSERT, &aRewriter);
666
667
0
    rEmbeddedObjectContainer.setUserAllowsLinkUpdate(bSaveUserAllowsLinkUpdate);
668
669
0
    return bActivate;
670
0
}
671
672
0
bool SwWrtShell::IsOLEMath() {
673
0
    svt::EmbeddedObjectRef& xRef = GetOLEObject();
674
0
    OSL_ENSURE( xRef.is(), "OLE not found" );
675
676
0
    const auto classId = xRef->getClassID();
677
0
    if ( SotExchange::IsMath(classId) )
678
0
        return true;
679
0
    return false;
680
0
}
681
682
// The current selected OLE object will be loaded with the
683
// verb into the server.
684
void SwWrtShell::LaunchOLEObj(sal_Int32 nVerb)
685
0
{
686
0
    if ( GetCntType() != CNT_OLE ||
687
0
         GetView().GetViewFrame().GetFrame().IsInPlace() )
688
0
        return;
689
690
0
    svt::EmbeddedObjectRef& xRef = GetOLEObject();
691
0
    OSL_ENSURE( xRef.is(), "OLE not found" );
692
693
    // LOK: we don't want to handle any other embedded objects than
694
    // charts, there are too many problems with eg. embedded spreadsheets
695
    // (like it creates a separate view for the calc sheet)
696
0
    if (comphelper::LibreOfficeKit::isActive())
697
0
    {
698
0
        const auto classId = xRef->getClassID();
699
0
        if (!SotExchange::IsChart(classId) && !SotExchange::IsMath(classId))
700
0
            return;
701
0
    }
702
703
0
    SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
704
0
    if ( !pCli )
705
0
        pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
706
707
0
    uno::Reference<lang::XInitialization> xOLEInit(xRef.GetObject(), uno::UNO_QUERY);
708
0
    if (xOLEInit.is())
709
0
    {
710
0
        uno::Sequence<beans::PropertyValue> aArguments
711
0
            = { comphelper::makePropertyValue(u"ReadOnly"_ustr, pCli->IsProtected()) };
712
0
        xOLEInit->initialize({ uno::Any(aArguments) });
713
0
    }
714
715
0
    static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
716
717
0
    CalcAndSetScale( xRef );
718
0
    pCli->DoVerb( nVerb );
719
720
0
    static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
721
0
    CalcAndSetScale( xRef );
722
0
}
723
724
void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
725
0
{
726
0
    try
727
0
    {
728
0
        sal_Int32 nState = xObj->getCurrentState();
729
0
        if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
730
0
          || nState == css::embed::EmbedStates::UI_ACTIVE )
731
0
        {
732
0
            SfxInPlaceClient* pCli =
733
0
                GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
734
0
            if ( pCli )
735
0
            {
736
0
                tools::Rectangle aArea = pCli->GetObjArea();
737
0
                aArea += rOffset;
738
0
                pCli->SetObjArea( aArea );
739
0
            }
740
0
        }
741
0
    }
742
0
    catch (const uno::Exception&)
743
0
    {
744
0
    }
745
0
}
746
747
void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
748
                                  const SwRect *pFlyPrtRect,
749
                                  const SwRect *pFlyFrameRect,
750
                                  const bool bNoTextFramePrtAreaChanged )
751
0
{
752
    // Setting the scale of the client. This arises from the difference
753
    // between the VisArea of the object and the ObjArea.
754
0
    OSL_ENSURE( xObj.is(), "ObjectRef not  valid" );
755
756
0
    sal_Int64 nAspect = xObj.GetViewAspect();
757
0
    if ( nAspect == embed::Aspects::MSOLE_ICON )
758
0
        return; // the replacement image is completely controlled by container in this case
759
760
0
    sal_Int64 nMisc = 0;
761
0
    bool bLinkingChart = false;
762
763
0
    try
764
0
    {
765
0
        nMisc = xObj->getStatus( nAspect );
766
767
        // This can surely only be a non-active object, if desired they
768
        // get the new size set as VisArea (StarChart).
769
0
        if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
770
0
        {
771
            // TODO/MBA: testing
772
0
            SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
773
0
                        : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
774
0
            if( !aRect.IsEmpty() )
775
0
            {
776
                // TODO/LEAN: getMapUnit can switch object to running state
777
                // xObj.TryRunningState();
778
779
0
                MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
780
781
                // TODO/LATER: needs complete VisArea?!
782
0
                Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
783
0
                awt::Size aSz;
784
0
                aSz.Width = aSize.Width();
785
0
                aSz.Height = aSize.Height();
786
787
                // Action 'setVisualAreaSize' doesn't have to turn on the
788
                // modified state of the document, either.
789
0
                bool bModified = false;
790
0
                uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
791
0
                if (xModifiable.is())
792
0
                    bModified = xModifiable->isModified();
793
0
                xObj->setVisualAreaSize( nAspect, aSz );
794
0
                xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
795
0
                if (xModifiable.is() && xModifiable->isModified() && !bModified)
796
0
                    xModifiable->setModified(bModified);
797
798
                // #i48419# - action 'UpdateReplacement' doesn't
799
                // have to change the modified state of the document.
800
                // This is only a workaround for the defect, that this action
801
                // modifies a document after load, because unnecessarily the
802
                // replacement graphic is updated, in spite of the fact that
803
                // nothing has been changed.
804
                // If the replacement graphic changes by this action, the document
805
                // will be already modified via other mechanisms.
806
0
                {
807
0
                    bool bResetEnableSetModified(false);
808
0
                    if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
809
0
                    {
810
0
                        GetDoc()->GetDocShell()->EnableSetModified( false );
811
0
                        bResetEnableSetModified = true;
812
0
                    }
813
814
                    //#i79576# don't destroy chart replacement images on load
815
                    //#i79578# don't request a new replacement image for charts to often
816
                    //a chart sends a modified call to the framework if it was changed
817
                    //thus the replacement update is already handled elsewhere
818
0
                    if ( !SotExchange::IsChart( xObj->getClassID() ) )
819
0
                        xObj.UpdateReplacement();
820
821
0
                    if ( bResetEnableSetModified )
822
0
                    {
823
0
                        GetDoc()->GetDocShell()->EnableSetModified();
824
0
                    }
825
0
                }
826
0
            }
827
828
            // TODO/LATER: this is only a workaround,
829
0
            uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
830
0
            bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
831
0
        }
832
0
    }
833
0
    catch (const uno::Exception&)
834
0
    {
835
        // TODO/LATER: handle the error
836
0
        return;
837
0
    }
838
839
0
    SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
840
0
    if ( !pCli )
841
0
    {
842
0
        if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
843
0
             || bLinkingChart
844
             // --> OD #i117189# - refine condition for non-resizable objects
845
             // non-resizable objects need to be set the size back by this method
846
0
             || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
847
0
        {
848
0
            pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
849
0
        }
850
0
        else
851
0
            return;
852
0
    }
853
854
    // TODO/LEAN: getMapUnit can switch object to running state
855
    // xObj.TryRunningState();
856
857
0
    awt::Size aSize;
858
0
    try
859
0
    {
860
0
        aSize = xObj->getVisualAreaSize( nAspect );
861
0
    }
862
0
    catch (const embed::NoVisualAreaSizeException&)
863
0
    {
864
0
        OSL_FAIL("Can't get visual area size!" );
865
        // the scaling will not be done
866
0
    }
867
0
    catch (const uno::Exception&)
868
0
    {
869
        // TODO/LATER: handle the error
870
0
        OSL_FAIL("Can't get visual area size!" );
871
0
        return;
872
0
    }
873
874
0
    Size _aVisArea( aSize.Width, aSize.Height );
875
876
0
    Fraction aScaleWidth( 1, 1 );
877
0
    Fraction aScaleHeight( 1, 1 );
878
879
0
    bool bUseObjectSize = false;
880
881
    // As long as there comes no reasonable size from the object,
882
    // nothing can be scaled.
883
0
    if( _aVisArea.Width() && _aVisArea.Height() )
884
0
    {
885
0
        const MapMode aTmp( MapUnit::MapTwip );
886
0
        MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
887
0
        _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
888
0
        Size aObjArea;
889
0
        if ( pFlyPrtRect )
890
0
            aObjArea = pFlyPrtRect->SSize();
891
0
        else
892
0
            aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
893
894
        // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
895
0
        tools::Long nX, nY;
896
0
        SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
897
0
        if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
898
0
               _aVisArea.Width() + nX >= aObjArea.Width() &&
899
0
               _aVisArea.Height()- nY <= aObjArea.Height()&&
900
0
               _aVisArea.Height()+ nY >= aObjArea.Height() ))
901
0
        {
902
0
            if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
903
0
            {
904
                // the object must not be scaled,
905
                // the size stored in object must be used for restoring
906
0
                bUseObjectSize = true;
907
0
            }
908
0
            else
909
0
            {
910
0
                aScaleWidth = Fraction( aObjArea.Width(),   _aVisArea.Width() );
911
0
                aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
912
0
            }
913
0
        }
914
0
    }
915
916
    // Now is the favorable time to set the ObjArea.
917
    // The Scaling must be considered.
918
0
    SwRect aArea;
919
0
    if ( pFlyPrtRect )
920
0
    {
921
0
        aArea = *pFlyPrtRect;
922
0
        aArea += pFlyFrameRect->Pos();
923
0
    }
924
0
    else
925
0
    {
926
0
        aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
927
0
        aArea += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
928
0
    }
929
930
0
    if ( bUseObjectSize )
931
0
    {
932
        // --> this moves non-resizable object so that when adding borders the baseline remains the same
933
0
        const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
934
0
        OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." );
935
0
        if ( pFlyFrameFormat )
936
0
        {
937
0
            const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
938
0
            SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
939
0
                        : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
940
0
            aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
941
0
        }
942
0
        aArea.Width ( _aVisArea.Width() );
943
0
        aArea.Height( _aVisArea.Height() );
944
0
        RequestObjectResize( aArea, xObj.GetObject() );
945
0
    }
946
0
    else
947
0
    {
948
0
        double nWidth(pCli->GetScaleWidth());
949
0
        double nHeight(pCli->GetScaleHeight());
950
0
        if (nWidth && nHeight)
951
0
        {
952
0
            aArea.Width ( aArea.Width()  / nWidth );
953
0
            aArea.Height( aArea.Height() / nHeight );
954
0
        }
955
0
    }
956
957
0
    pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
958
0
}
959
960
void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
961
                            const SwRect &rFrame )
962
0
{
963
0
    SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
964
0
    if ( !pCli )
965
0
        new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
966
0
    CalcAndSetScale( xObj, &rPrt, &rFrame );
967
0
}
968
969
// Insert hard page break;
970
// Selections will be overwritten
971
void SwWrtShell::InsertPageBreak(const UIName *pPageDesc, const ::std::optional<sal_uInt16>& oPgNum )
972
0
{
973
0
    if (!lcl_IsAllowed(this))
974
0
        return;
975
976
0
    ResetCursorStack();
977
0
    if( CanInsert() )
978
0
    {
979
0
        SwActContext aActContext(this);
980
0
        StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
981
982
0
        if ( !IsCursorInTable() )
983
0
        {
984
0
            if(HasSelection())
985
0
                DelRight();
986
0
            SwFEShell::SplitNode();
987
            // delete the numbered attribute of the last line if the last line is empty
988
0
            GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
989
0
        }
990
991
0
        const SwPageDesc *pDesc = pPageDesc
992
0
                                ? FindPageDescByName( *pPageDesc, true ) : nullptr;
993
0
        if( pDesc )
994
0
        {
995
0
            SwFormatPageDesc aDesc( pDesc );
996
0
            aDesc.SetNumOffset( oPgNum );
997
0
            SetAttrItem( aDesc );
998
0
        }
999
0
        else
1000
0
            SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
1001
0
        EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
1002
0
    }
1003
0
    collectUIInformation(u"BREAK_PAGE"_ustr, u"parameter"_ustr);
1004
0
}
1005
1006
// Insert enclosing characters
1007
// Selections will be overwritten
1008
void SwWrtShell::InsertEnclosingChars(const OUString& sStartStr, const OUString& sEndStr)
1009
0
{
1010
0
    if (!lcl_IsAllowed(this) || !CanInsert())
1011
0
        return;
1012
0
    StartAllAction();
1013
0
    StartUndo();
1014
1015
0
    OUStringBuffer currentText, newText;
1016
0
    bool dotsAdded = false;
1017
0
    const OUString dots = SwResId(STR_LDOTS);
1018
0
    for (SwPaM& rPaM : SwWrtShell::GetCursor()->GetRingContainer())
1019
0
    {
1020
0
        if (*rPaM.GetPoint() == *rPaM.GetMark())
1021
0
            continue;
1022
0
        if (newText.isEmpty())
1023
0
        {
1024
0
            OUString pamText = ShortenString(rPaM.GetText(), nUndoStringLength, dots)
1025
0
                                   .replaceAll("\n", " ");
1026
0
            currentText.append(pamText);
1027
0
            newText.append(sStartStr + pamText + sEndStr);
1028
0
        }
1029
0
        else if (!dotsAdded)
1030
0
        {
1031
0
            dotsAdded = true;
1032
0
            currentText.append(dots);
1033
0
            newText.append(dots);
1034
0
        }
1035
1036
0
        {
1037
0
            SwPaM aLocalPam(rPaM, nullptr);
1038
0
            aLocalPam.Normalize(); // point is at start now
1039
0
            auto& contentOperations = SwViewShell::getIDocumentContentOperations();
1040
1041
            // To copy the formatting of the start of the range, insert the start string in two
1042
            // phases: insert it after the first selected character; and then move it back
1043
0
            SwPosition posStart = *aLocalPam.GetPoint();
1044
0
            aLocalPam.GetPoint()->AdjustContent(+1);
1045
0
            contentOperations.InsertString(aLocalPam, sStartStr);
1046
            // Now aLocalPam's point is *after* the inserted string
1047
0
            SwPaM insertedPaM(*aLocalPam.GetPoint());
1048
0
            insertedPaM.SetMark();
1049
0
            insertedPaM.GetPoint()->AdjustContent(-sStartStr.getLength());
1050
0
            contentOperations.CopyRange(insertedPaM, posStart, SwCopyFlags::CopyAll);
1051
0
            contentOperations.DeleteRange(insertedPaM);
1052
1053
            // No such problems with end string
1054
0
            aLocalPam.Exchange(); // point is at end now
1055
0
            contentOperations.InsertString(aLocalPam, sEndStr);
1056
0
        }
1057
0
        rPaM.Start()->AdjustContent(-sStartStr.getLength()); // now the selection includes insertion
1058
0
    }
1059
1060
0
    SwRewriter aRewriter;
1061
0
    aRewriter.AddRule(UndoArg1, currentText.makeStringAndClear());
1062
0
    aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
1063
0
    aRewriter.AddRule(UndoArg3, newText.makeStringAndClear());
1064
0
    EndUndo(SwUndoId::UI_REPLACE, &aRewriter);
1065
1066
0
    EndAllAction();
1067
0
}
1068
1069
// Insert hard page break;
1070
// Selections will be overwritten
1071
1072
void SwWrtShell::InsertLineBreak(std::optional<SwLineBreakClear> oClear)
1073
0
{
1074
0
    if (!lcl_IsAllowed(this))
1075
0
        return;
1076
1077
0
    ResetCursorStack();
1078
0
    if( CanInsert() )
1079
0
    {
1080
0
        if(HasSelection())
1081
0
            DelRight();
1082
1083
0
        const sal_Unicode cIns = 0x0A;
1084
0
        SwLineBreakClear eClear = SwLineBreakClear::NONE;
1085
0
        if (oClear.has_value())
1086
0
        {
1087
0
            eClear = *oClear;
1088
0
        }
1089
0
        SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
1090
0
        if (pACorr && eClear == SwLineBreakClear::NONE)
1091
0
            AutoCorrect( *pACorr, cIns );
1092
0
        else
1093
0
        {
1094
0
            if (eClear == SwLineBreakClear::NONE)
1095
0
            {
1096
0
                SwWrtShell::Insert(OUString(cIns));
1097
0
            }
1098
0
            else
1099
0
            {
1100
0
                SwFormatLineBreak aLineBreak(eClear);
1101
0
                SetAttrItem(aLineBreak);
1102
0
            }
1103
0
        }
1104
0
    }
1105
0
}
1106
1107
// Insert hard column break;
1108
// Selections will be overwritten
1109
1110
void SwWrtShell::InsertColumnBreak()
1111
0
{
1112
0
    if (!lcl_IsAllowed(this))
1113
0
        return;
1114
1115
0
    SwActContext aActContext(this);
1116
0
    ResetCursorStack();
1117
0
    if( !CanInsert() )
1118
0
        return;
1119
1120
0
    StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
1121
1122
0
    if ( !IsCursorInTable() )
1123
0
    {
1124
0
        if(HasSelection())
1125
0
            DelRight();
1126
0
        SwFEShell::SplitNode(false);
1127
0
    }
1128
0
    SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
1129
1130
0
    EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
1131
0
}
1132
1133
void SwWrtShell::InsertContentControl(SwContentControlType eType)
1134
0
{
1135
0
    if (!lcl_IsAllowed(this))
1136
0
    {
1137
0
        return;
1138
0
    }
1139
1140
0
    ResetCursorStack();
1141
0
    if (!CanInsert())
1142
0
    {
1143
0
        return;
1144
0
    }
1145
1146
0
    auto pContentControl = std::make_shared<SwContentControl>(nullptr);
1147
1148
    // Make Random ID... check if it is unique
1149
    // warning: possible infinite loop if there would be billions of content controls.
1150
0
    SwContentControlManager& pManager = GetDoc()->GetContentControlManager();
1151
0
    size_t nCCCount = pManager.GetCount();
1152
0
    sal_Int32 nIdToCheck;
1153
0
    nIdToCheck
1154
0
        = comphelper::rng::uniform_uint_distribution(1, std::numeric_limits<sal_Int32>::max());
1155
0
    size_t nIdx = 0;
1156
0
    while (nIdx < nCCCount)
1157
0
    {
1158
0
        sal_Int32 nID
1159
0
            = pManager.UnsortedGet(nIdx)->GetContentControl().GetContentControl()->GetId();
1160
0
        if (nID == nIdToCheck)
1161
0
        {
1162
0
            nIdToCheck = comphelper::rng::uniform_uint_distribution(
1163
0
                1, std::numeric_limits<sal_Int32>::max());
1164
0
            nIdx = 0;
1165
0
        }
1166
0
        else
1167
0
            nIdx++;
1168
0
    }
1169
0
    pContentControl->SetId(nIdToCheck);
1170
1171
0
    OUString aPlaceholder;
1172
0
    switch (eType)
1173
0
    {
1174
0
        case SwContentControlType::RICH_TEXT:
1175
0
        case SwContentControlType::PLAIN_TEXT:
1176
0
        {
1177
0
            pContentControl->SetShowingPlaceHolder(true);
1178
0
            if (eType == SwContentControlType::PLAIN_TEXT)
1179
0
            {
1180
0
                pContentControl->SetPlainText(true);
1181
0
            }
1182
0
            if (!HasSelection())
1183
0
            {
1184
0
                aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER);
1185
0
            }
1186
0
            break;
1187
0
        }
1188
0
        case SwContentControlType::CHECKBOX:
1189
0
        {
1190
0
            pContentControl->SetCheckbox(true);
1191
0
            pContentControl->SetCheckedState(SwContentControl::CHECKED_STATE);
1192
0
            pContentControl->SetUncheckedState(SwContentControl::UNCHECKED_STATE);
1193
0
            aPlaceholder = u"\u2610"_ustr;
1194
0
            break;
1195
0
        }
1196
0
        case SwContentControlType::COMBO_BOX:
1197
0
        case SwContentControlType::DROP_DOWN_LIST:
1198
0
        {
1199
0
            if (eType == SwContentControlType::COMBO_BOX)
1200
0
            {
1201
0
                pContentControl->SetComboBox(true);
1202
0
            }
1203
0
            else if (eType == SwContentControlType::DROP_DOWN_LIST)
1204
0
            {
1205
0
                pContentControl->SetDropDown(true);
1206
0
            }
1207
1208
0
            pContentControl->SetShowingPlaceHolder(true);
1209
0
            if (!HasSelection())
1210
0
            {
1211
0
                aPlaceholder = SwResId(STR_DROPDOWN_CONTENT_CONTROL_PLACEHOLDER);
1212
0
            }
1213
0
            SwContentControlListItem aListItem;
1214
0
            aListItem.m_aValue = aPlaceholder;
1215
0
            pContentControl->SetListItems({ std::move(aListItem) });
1216
0
            break;
1217
0
        }
1218
0
        case SwContentControlType::PICTURE:
1219
0
        {
1220
            // Set up the picture content control.
1221
0
            pContentControl->SetShowingPlaceHolder(true);
1222
0
            pContentControl->SetPicture(true);
1223
1224
            // Create the placeholder bitmap.
1225
0
            Bitmap aBitmap(Size(1, 1), vcl::PixelFormat::N24_BPP);
1226
0
            Color aColor = SvtOptionsDrawinglayer::getHilightColor();
1227
0
            aColor.IncreaseLuminance(255 * 0.75);
1228
0
            aBitmap.Erase(aColor);
1229
0
            SwRewriter aRewriter;
1230
0
            aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC_DEFNAME));
1231
0
            StartUndo(SwUndoId::INSERT, &aRewriter);
1232
0
            LockPaint(LockPaintReason::InsertGraphic);
1233
0
            StartAction();
1234
0
            InsertGraphic(OUString(), OUString(), aBitmap, nullptr, RndStdIds::FLY_AS_CHAR);
1235
1236
            // Set properties on the bitmap.
1237
0
            SfxItemSetFixed<RES_FRM_SIZE, RES_FRM_SIZE> aSet(GetDoc()->GetAttrPool());
1238
0
            GetFlyFrameAttr(aSet);
1239
0
            SwFormatFrameSize aSize(SwFrameSize::Fixed, 3000, 3000);
1240
0
            aSet.Put(aSize);
1241
0
            SetFlyFrameAttr(aSet);
1242
0
            SwFrameFormat* pFrameFormat = GetFlyFrameFormat();
1243
0
            EndAction();
1244
0
            UnlockPaint();
1245
0
            EndUndo();
1246
1247
            // Go after the anchor position.
1248
0
            UnSelectFrame();
1249
0
            LeaveSelFrameMode();
1250
0
            {
1251
0
                SwCursor* pCursor = getShellCursor(true);
1252
0
                pCursor->DeleteMark();
1253
0
                const SwFormatAnchor& rFormatAnchor = pFrameFormat->GetAnchor();
1254
0
                pCursor->GetPoint()->Assign( *rFormatAnchor.GetAnchorContentNode(), rFormatAnchor.GetAnchorContentOffset() + 1);
1255
0
            }
1256
1257
            // Select before the anchor position.
1258
0
            Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1259
0
            break;
1260
0
        }
1261
0
        case SwContentControlType::DATE:
1262
0
        {
1263
0
            pContentControl->SetShowingPlaceHolder(true);
1264
0
            pContentControl->SetDate(true);
1265
0
            SvNumberFormatter* pFormatter = GetDoc()->GetNumberFormatter();
1266
0
            sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
1267
0
            const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
1268
0
            pContentControl->SetDateFormat(pFormat->GetFormatstring());
1269
0
            pContentControl->SetDateLanguage(LanguageTag(pFormat->GetLanguage()).getBcp47());
1270
0
            if (!HasSelection())
1271
0
            {
1272
0
                aPlaceholder = SwResId(STR_DATE_CONTENT_CONTROL_PLACEHOLDER);
1273
0
            }
1274
0
            break;
1275
0
        }
1276
0
    }
1277
0
    if (aPlaceholder.getLength())
1278
0
    {
1279
0
        Insert(aPlaceholder);
1280
0
        Left(SwCursorSkipMode::Chars, /*bSelect=*/true, aPlaceholder.getLength(),
1281
0
                /*bBasicCall=*/false);
1282
0
    }
1283
1284
0
    const RedlineFlags oldRedlineFlags = getIDocumentRedlineAccess().GetRedlineFlags();
1285
0
    getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::Ignore);
1286
0
    SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL);
1287
0
    SetAttrItem(aContentControl);
1288
0
    getIDocumentRedlineAccess().SetRedlineFlags(oldRedlineFlags);
1289
0
}
1290
1291
// Insert footnote
1292
// rStr - optional footnote mark
1293
1294
void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
1295
0
{
1296
0
    ResetCursorStack();
1297
0
    if( !CanInsert() )
1298
0
        return;
1299
1300
0
    if(HasSelection())
1301
0
    {
1302
        //collapse cursor to the end
1303
0
        if(!IsCursorPtAtEnd())
1304
0
            SwapPam();
1305
0
        ClearMark();
1306
0
    }
1307
0
    SwPosition aPos = *GetCursor()->GetPoint();
1308
0
    SwFormatFootnote aFootNote( bEndNote );
1309
0
    if(!rStr.isEmpty())
1310
0
        aFootNote.SetNumStr( rStr );
1311
1312
0
    SetAttrItem(aFootNote);
1313
1314
0
    if( bEdit )
1315
0
    {
1316
        // For editing the footnote text.
1317
0
        Left(SwCursorSkipMode::Chars, false, 1, false );
1318
0
        GotoFootnoteText();
1319
0
    }
1320
0
    m_aNavigationMgr.addEntry(aPos);
1321
0
}
1322
1323
// tdf#141634
1324
static bool lcl_FoldedOutlineNodeEndOfParaSplit(SwWrtShell* pThis)
1325
0
{
1326
0
    SwTextNode* pTextNode = pThis->GetCursor()->GetPointNode().GetTextNode();
1327
0
    const SwNodes& rNodes = pThis->GetNodes();
1328
0
    const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
1329
0
    SwOutlineNodes::size_type nPos;
1330
1331
0
    if (!pTextNode || pTextNode->GetAttrOutlineContentVisible()
1332
0
        || !rOutlineNodes.Seek_Entry(pTextNode, &nPos))
1333
0
        return false;
1334
1335
0
    SwNode* pSttNd = rOutlineNodes[nPos];
1336
1337
    // determine end node of folded outline content
1338
0
    SwNode* pEndNd = &rNodes.GetEndOfContent();
1339
0
    if (rOutlineNodes.size() > nPos + 1)
1340
0
        pEndNd = rOutlineNodes[nPos + 1];
1341
1342
0
    if (pThis->GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
1343
0
    {
1344
        // get the next outline node after the folded outline content (iPos)
1345
        // it is the next outline node with the same level or less
1346
0
        int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
1347
0
        SwOutlineNodes::size_type iPos = nPos;
1348
0
        while (++iPos < rOutlineNodes.size()
1349
0
               && rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel)
1350
0
            ;
1351
1352
        // get the correct end node
1353
        // the outline node may be in frames, headers, footers special section of doc model
1354
0
        SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
1355
0
        while (pStartOfSectionNodeSttNd->StartOfSectionNode()
1356
0
               != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
1357
0
        {
1358
0
            pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
1359
0
        }
1360
0
        pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
1361
1362
0
        if (iPos < rOutlineNodes.size())
1363
0
        {
1364
0
            SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
1365
0
            while (pStartOfSectionNode->StartOfSectionNode()
1366
0
                   != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
1367
0
            {
1368
0
                pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
1369
0
            }
1370
0
            if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
1371
0
                pEndNd = rOutlineNodes[iPos];
1372
0
        }
1373
0
    }
1374
1375
    // table, text box, header, footer
1376
0
    if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
1377
0
    {
1378
        // insert before section end node
1379
0
        if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
1380
0
        {
1381
0
            SwNodeIndex aIdx(*pSttNd->EndOfSectionNode());
1382
0
            while (aIdx.GetNode().IsEndNode())
1383
0
                --aIdx;
1384
0
            ++aIdx;
1385
0
            pEndNd = &aIdx.GetNode();
1386
0
        }
1387
0
    }
1388
    // if pSttNd isn't in table but pEndNd is then insert after table
1389
0
    else if (pEndNd->GetTableBox())
1390
0
    {
1391
0
        pEndNd = pEndNd->FindTableNode();
1392
0
        SwNodeIndex aIdx(*pEndNd, -1);
1393
        // account for nested tables
1394
0
        while (aIdx.GetNode().GetTableBox())
1395
0
        {
1396
0
            pEndNd = aIdx.GetNode().FindTableNode();
1397
0
            aIdx.Assign(*pEndNd, -1);
1398
0
        }
1399
0
        aIdx.Assign(*pEndNd->EndOfSectionNode(), +1);
1400
0
        pEndNd = &aIdx.GetNode();
1401
0
    }
1402
    // end node determined
1403
1404
    // now insert the new outline node
1405
0
    SwDoc* pDoc = pThis->GetDoc();
1406
1407
    // insert at end of tablebox doesn't work correct without
1408
0
    MakeAllOutlineContentTemporarilyVisible a(pDoc);
1409
1410
0
    SwTextNode* pNd = pDoc->GetNodes().MakeTextNode(*pEndNd, pTextNode->GetTextColl(), true);
1411
1412
    // if the outline level is not set in style then it is set in direct formatting
1413
0
    if (!pTextNode->GetTextColl()->GetAttrOutlineLevel())
1414
0
        pNd->SetAttrOutlineLevel(pTextNode->GetAttrOutlineLevel());
1415
1416
0
    (void)rOutlineNodes.Seek_Entry(pNd, &nPos);
1417
0
    pThis->GotoOutline(nPos);
1418
1419
0
    if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1420
0
    {
1421
0
        pDoc->GetIDocumentUndoRedo().ClearRedo();
1422
0
        pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsert>(*pNd));
1423
0
        pDoc->GetIDocumentUndoRedo().AppendUndo(
1424
0
            std::make_unique<SwUndoFormatColl>(SwPaM(*pNd), pNd->GetTextColl(), true, true));
1425
0
        if (!pTextNode->GetTextColl()->GetAttrOutlineLevel())
1426
0
            pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoAttr>(
1427
0
                SwPaM(*pNd),
1428
0
                SfxUInt16Item(RES_PARATR_OUTLINELEVEL, pTextNode->GetAttrOutlineLevel()),
1429
0
                SetAttrMode::DEFAULT));
1430
0
    }
1431
1432
0
    pThis->SetModified();
1433
0
    return true;
1434
0
}
1435
1436
// SplitNode; also, because
1437
//                  - of deleting selected content;
1438
//                  - of reset of the Cursorstack if necessary.
1439
1440
void SwWrtShell::SplitNode( bool bAutoFormat )
1441
0
{
1442
0
    ResetCursorStack();
1443
0
    if( !CanInsert() )
1444
0
        return;
1445
1446
0
    SwActContext aActContext(this);
1447
1448
0
    m_rView.GetEditWin().FlushInBuffer();
1449
0
    StartUndo(SwUndoId::SPLITNODE);
1450
1451
0
    bool bHasSel = HasSelection();
1452
0
    if (bHasSel)
1453
0
        DelRight();
1454
1455
0
    bool bHandled = false;
1456
0
    if (GetViewOptions()->IsShowOutlineContentVisibilityButton() && IsEndPara())
1457
0
        bHandled = lcl_FoldedOutlineNodeEndOfParaSplit(this);
1458
1459
0
    if (!bHandled)
1460
0
        SwFEShell::SplitNode();
1461
1462
0
    EndUndo(SwUndoId::SPLITNODE);
1463
1464
    // run autoformat after "New Paragraph" undo, so it can be undone separately from the newline
1465
0
    if (!bHandled && bAutoFormat)
1466
0
        AutoFormatBySplitNode();
1467
0
}
1468
1469
// Turn on numbering
1470
// Parameter:   Optional specification of a name for the named list;
1471
//              this indicates a position if it is possible to convert them
1472
//              into a number and less than nMaxRules.
1473
1474
// To test the CharFormats at the numbering
1475
// external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
1476
1477
// -> #i40041#
1478
// Preconditions (as far as OD has figured out):
1479
// - <SwEditShell::HasNumber()> is false, if <bNum> is true
1480
// - <SwEditShell::HasBullet()> is false, if <bNum> is false
1481
// Behavior of method is determined by the current situation at the current
1482
// cursor position in the document.
1483
void SwWrtShell::NumOrBulletOn(bool bNum)
1484
0
{
1485
0
    StartUndo(SwUndoId::NUMORNONUM);
1486
1487
0
    const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
1488
1489
    // - activate outline rule respectively turning on outline rule for
1490
    //   current text node. But, only for turning on a numbering (<bNum> == true).
1491
    // - overwrite found numbering rule at current cursor position, if
1492
    //   no numbering rule can be retrieved from the paragraph style.
1493
0
    bool bContinueFoundNumRule( false );
1494
0
    bool bActivateOutlineRule( false );
1495
0
    int nActivateOutlineLvl( MAXLEVEL );    // only relevant, if <bActivateOutlineRule> == true
1496
0
    SwTextFormatColl * pColl = GetCurTextFormatColl();
1497
0
    if ( pColl )
1498
0
    {
1499
        // retrieve numbering rule at paragraph
1500
        // style, which is found at current cursor position in the document.
1501
0
        SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
1502
        // #125993# - The outline numbering rule isn't allowed
1503
        // to be derived from a parent paragraph style to a derived one.
1504
        // Thus check, if the found outline numbering rule is directly
1505
        // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
1506
0
        if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
1507
0
        {
1508
0
            const SwNumRule* pDirectCollRule =
1509
0
                    mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
1510
0
            if ( !pDirectCollRule )
1511
0
            {
1512
0
                pCollRule = nullptr;
1513
0
            }
1514
0
        }
1515
1516
0
        if ( !pCollRule )
1517
0
        {
1518
0
            pNumRule = pCollRule;
1519
0
        }
1520
        // no activation or continuation of outline numbering in Writer/Web document
1521
0
        else if ( bNum &&
1522
0
                  !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
1523
0
                  pCollRule == GetDoc()->GetOutlineNumRule() )
1524
0
        {
1525
0
            if ( pNumRule == pCollRule )
1526
0
            {
1527
                // check, if text node at current cursor positioned is counted.
1528
                // If not, let it been counted. Then it has to be checked,
1529
                // of the outline numbering has to be activated or continued.
1530
0
                SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1531
0
                        *GetLayout(), GetCursor()->GetPoint()->GetNode());
1532
0
                if ( pTextNode && !pTextNode->IsCountedInList() )
1533
0
                {
1534
                    // check, if numbering of the outline level of the paragraph
1535
                    // style is active. If not, activate this outline level.
1536
0
                    nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1537
0
                    OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
1538
0
                            "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
1539
0
                    if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1540
0
                         pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1541
0
                            == SVX_NUM_NUMBER_NONE )
1542
0
                    {
1543
                        // activate outline numbering
1544
0
                        bActivateOutlineRule = true;
1545
0
                    }
1546
0
                    else
1547
0
                    {
1548
                        // turning on outline numbering at current cursor position
1549
0
                        bContinueFoundNumRule = true;
1550
0
                    }
1551
0
                }
1552
0
                else
1553
0
                {
1554
                    // #i101234#
1555
                    // activate outline numbering, because from the precondition
1556
                    // it's known, that <SwEdit::HasNumber()> == false
1557
0
                    bActivateOutlineRule = true;
1558
0
                    nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1559
0
                }
1560
0
            }
1561
0
            else if ( !pNumRule )
1562
0
            {
1563
                // #i101234#
1564
                // Check, if corresponding list level of the outline numbering
1565
                // has already a numbering format set.
1566
0
                nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1567
0
                if ( pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1568
0
                                == SVX_NUM_NUMBER_NONE )
1569
0
                {
1570
                    // activate outline numbering, because from the precondition
1571
                    // it's known, that <SwEdit::HasNumber()> == false
1572
0
                    bActivateOutlineRule = true;
1573
0
                }
1574
0
                else
1575
0
                {
1576
                    // turning on outline numbering at current cursor position
1577
0
                    bContinueFoundNumRule = true;
1578
0
                }
1579
0
            }
1580
0
            else
1581
0
            {
1582
                // check, if numbering of the outline level of the paragraph
1583
                // style is active. If not, activate this outline level.
1584
0
                nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
1585
0
                OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
1586
0
                        "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
1587
0
                if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
1588
0
                     pCollRule->Get( o3tl::narrowing<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
1589
0
                        == SVX_NUM_NUMBER_NONE )
1590
0
                {
1591
                    // activate outline numbering
1592
0
                    bActivateOutlineRule = true;
1593
0
                }
1594
0
                else
1595
0
                {
1596
                    // turning on outline numbering at current cursor position
1597
0
                    bContinueFoundNumRule = true;
1598
0
                }
1599
0
            }
1600
0
            pNumRule = pCollRule;
1601
0
        }
1602
0
    }
1603
1604
    // Only automatic numbering/bullet rules should be changed.
1605
    // Note: The outline numbering rule is also an automatic one. It's only
1606
    //       changed, if it has to be activated.
1607
0
    if ( pNumRule )
1608
0
    {
1609
0
        if ( !pNumRule->IsAutoRule() )
1610
0
        {
1611
0
            pNumRule = nullptr;
1612
0
        }
1613
0
        else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
1614
0
                  !bActivateOutlineRule && !bContinueFoundNumRule )
1615
0
        {
1616
0
            pNumRule = nullptr;
1617
0
        }
1618
0
    }
1619
1620
    // Search for a previous numbering/bullet rule to continue it.
1621
0
    OUString sContinuedListId;
1622
0
    if ( !pNumRule )
1623
0
    {
1624
0
        pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
1625
0
                                            false, bNum, false, 0,
1626
0
                                            sContinuedListId, GetLayout() );
1627
0
        bContinueFoundNumRule = pNumRule != nullptr;
1628
0
    }
1629
1630
0
    if (pNumRule)
1631
0
    {
1632
0
        SwNumRule aNumRule(*pNumRule);
1633
1634
        // do not change found numbering/bullet rule, if it should only be continued.
1635
0
        if ( !bContinueFoundNumRule )
1636
0
        {
1637
0
            SwTextNode const*const pTextNode = sw::GetParaPropsNode(
1638
0
                    *GetLayout(), GetCursor()->GetPoint()->GetNode());
1639
1640
0
            if (pTextNode)
1641
0
            {
1642
                // use above retrieve outline level, if outline numbering has to be activated.
1643
0
                int nLevel = bActivateOutlineRule
1644
0
                              ? nActivateOutlineLvl
1645
0
                              : pTextNode->GetActualListLevel();
1646
1647
0
                if (nLevel < 0)
1648
0
                    nLevel = 0;
1649
1650
0
                if (nLevel >= MAXLEVEL)
1651
0
                    nLevel = MAXLEVEL - 1;
1652
1653
0
                SwNumFormat aFormat(aNumRule.Get(o3tl::narrowing<sal_uInt16>(nLevel)));
1654
1655
0
                if (bNum)
1656
0
                    aFormat.SetNumberingType(SVX_NUM_ARABIC);
1657
0
                else
1658
0
                {
1659
                    // #i63395# Only apply user defined default bullet font
1660
0
                    if ( numfunc::IsDefBulletFontUserDefined() )
1661
0
                    {
1662
0
                        const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
1663
0
                        aFormat.SetBulletFont( pFnt );
1664
0
                    }
1665
0
                    aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
1666
0
                    aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1667
                    // #i93908# clear suffix for bullet lists
1668
0
                    aFormat.SetListFormat(u""_ustr, u""_ustr, nLevel);
1669
0
                }
1670
0
                aNumRule.Set(o3tl::narrowing<sal_uInt16>(nLevel), aFormat);
1671
0
            }
1672
0
        }
1673
1674
        // reset indent attribute on applying list style
1675
0
        SetCurNumRule( aNumRule, false, sContinuedListId, true );
1676
0
    }
1677
0
    else
1678
0
    {
1679
        // #i95907#
1680
0
        const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1681
0
                                    numfunc::GetDefaultPositionAndSpaceMode() );
1682
0
        SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
1683
        // Append the character template at the numbering.
1684
0
        SwCharFormat* pChrFormat;
1685
0
        SwDocShell* pDocSh = GetView().GetDocShell();
1686
1687
0
        if (bNum)
1688
0
        {
1689
0
            pChrFormat = GetCharFormatFromPool( SwPoolFormatId::CHR_NUM_LEVEL );
1690
0
        }
1691
0
        else
1692
0
        {
1693
0
            pChrFormat = GetCharFormatFromPool( SwPoolFormatId::CHR_BULLET_LEVEL );
1694
0
        }
1695
1696
0
        const SwTextNode *const pTextNode = sw::GetParaPropsNode(*GetLayout(),
1697
0
                GetCursor()->GetPoint()->GetNode());
1698
0
        const SwTwips nWidthOfTabs = pTextNode
1699
0
                                     ? pTextNode->GetWidthOfLeadingTabs()
1700
0
                                     : 0;
1701
0
        GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace(*GetCursor());
1702
1703
0
        const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) !=  nullptr;
1704
0
        const bool bRightToLeft = IsInRightToLeftText();
1705
0
        for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
1706
0
        {
1707
0
            SwNumFormat aFormat( aNumRule.Get( nLvl ) );
1708
0
            aFormat.SetCharFormat( pChrFormat );
1709
1710
0
            if (! bNum)
1711
0
            {
1712
0
                static constexpr OUString sDefaultBulletSymbol = u"•"_ustr;
1713
0
                static constexpr OUString sDefaultBulletSymbolFont = u"OpenSymbol"_ustr;
1714
0
                uno::Sequence<OUString> aBulletSymbols(
1715
0
                    officecfg::Office::Common::BulletsNumbering::DefaultListBullets::get());
1716
0
                uno::Sequence<OUString> aBulletSymbolsFonts(
1717
0
                    officecfg::Office::Common::BulletsNumbering::DefaultListBulletsFonts::get());
1718
0
                if (!aBulletSymbols.hasElements())
1719
0
                {
1720
0
                    SAL_WARN("sw", "empty DefaultListBullets config, adding a default single bullet");
1721
                    // Add a single element even if user cleared the list in the config
1722
0
                    aBulletSymbols.realloc(1);
1723
0
                    aBulletSymbols.getArray()[0] = sDefaultBulletSymbol;
1724
0
                }
1725
0
                const sal_Int32 nBulletSymbolIndex = nLvl % aBulletSymbols.getLength();
1726
0
                aFormat.SetBulletChar(aBulletSymbols[nBulletSymbolIndex].toChar());
1727
0
                vcl::Font aFont;
1728
                // Symbol and font correspond to each other, use same index
1729
0
                if (nBulletSymbolIndex < aBulletSymbolsFonts.getLength())
1730
0
                    aFont.SetFamilyName(aBulletSymbolsFonts[nBulletSymbolIndex]);
1731
0
                else
1732
0
                    aFont.SetFamilyName(sDefaultBulletSymbolFont);
1733
0
                aFormat.SetBulletFont(&aFont);
1734
0
                aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1735
                // #i93908# clear suffix for bullet lists
1736
0
                aFormat.SetListFormat(u""_ustr, u""_ustr, nLvl);
1737
0
            }
1738
1739
            // #i95907#
1740
0
            if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1741
0
            {
1742
0
                if(bHtml && nLvl)
1743
0
                {
1744
                    // 1/2" for HTML
1745
0
                    aFormat.SetAbsLSpace(nLvl * 720);
1746
0
                }
1747
0
                else if ( nWidthOfTabs > 0 )
1748
0
                {
1749
0
                    aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
1750
0
                }
1751
0
            }
1752
1753
            // #i38904#  Default alignment for
1754
            // numbering/bullet should be rtl in rtl paragraph:
1755
0
            if ( bRightToLeft )
1756
0
            {
1757
0
                aFormat.SetNumAdjust( SvxAdjust::Right );
1758
0
            }
1759
1760
0
            aNumRule.Set( nLvl, aFormat );
1761
0
        }
1762
1763
        // #i95907#
1764
0
        if ( pTextNode &&
1765
0
             ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1766
0
        {
1767
1768
0
            const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
1769
0
            if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
1770
0
            {
1771
                // #i111172#/fdo#85666
1772
                // If text node is already inside a list, assure that the indents
1773
                // are the same. Thus, adjust the indent change value by subtracting
1774
                // indents of to be applied list style.
1775
0
                SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
1776
0
                if ( pTextNode->GetNumRule() )
1777
0
                {
1778
0
                    int nLevel = pTextNode->GetActualListLevel();
1779
1780
0
                    if (nLevel < 0)
1781
0
                        nLevel = 0;
1782
1783
0
                    if (nLevel >= MAXLEVEL)
1784
0
                        nLevel = MAXLEVEL - 1;
1785
1786
0
                    const SwNumFormat& aFormat( aNumRule.Get( nLevel ) );
1787
0
                    if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1788
0
                    {
1789
0
                        nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
1790
0
                    }
1791
0
                }
1792
0
                aNumRule.ChangeIndent( nIndentChange );
1793
0
            }
1794
0
        }
1795
        // reset indent attribute on applying list style
1796
        // start new list
1797
0
        SetCurNumRule( aNumRule, true, OUString(), true );
1798
0
    }
1799
1800
0
    EndUndo(SwUndoId::NUMORNONUM);
1801
0
}
1802
// <- #i40041#
1803
1804
void SwWrtShell::NumOn()
1805
0
{
1806
0
    NumOrBulletOn(true);
1807
0
}
1808
1809
void SwWrtShell::NumOrBulletOff()
1810
0
{
1811
0
    const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
1812
1813
0
    if (!pCurNumRule)
1814
0
        return;
1815
1816
0
    DelNumRules();
1817
1818
    // #126346# - Cursor can not be anymore in front of
1819
    // a label, because numbering/bullet is switched off.
1820
0
    SetInFrontOfLabel( false );
1821
0
}
1822
// <- #i29560#
1823
1824
// Request Default-Bulletlist
1825
1826
void SwWrtShell::BulletOn()
1827
0
{
1828
0
    NumOrBulletOn(false);
1829
0
}
1830
1831
SelectionType SwWrtShell::GetSelectionType() const
1832
11.1k
{
1833
    // ContentType cannot be determined within a Start-/EndAction.
1834
    // Because there is no invalid value TEXT will be returned.
1835
    // The value does not matter, it may be updated in EndAction anyway.
1836
1837
11.1k
    if (ActionPend())
1838
0
        return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
1839
1840
11.1k
    SwView &_rView = const_cast<SwView&>(GetView());
1841
11.1k
    if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
1842
0
        return SelectionType::PostIt;
1843
1844
    // Inserting a frame is not a DrawMode
1845
11.1k
    SelectionType nCnt;
1846
11.1k
    if ( !_rView.GetEditWin().IsFrameAction() &&
1847
11.1k
        (GetSelectedObjCount() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
1848
0
    {
1849
0
        if (GetDrawView()->IsTextEdit())
1850
0
            nCnt = SelectionType::DrawObjectEditMode;
1851
0
        else
1852
0
        {
1853
0
            if (GetView().IsFormMode()) // Only Form selected
1854
0
                nCnt = SelectionType::DbForm;
1855
0
            else
1856
0
                nCnt = SelectionType::DrawObject;            // Any draw object
1857
1858
0
            if (_rView.IsBezierEditMode())
1859
0
                nCnt |= SelectionType::Ornament;
1860
0
            else if( GetDrawView()->GetContext() == SdrViewContext::Media )
1861
0
                nCnt |= SelectionType::Media;
1862
1863
0
            if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
1864
0
            {
1865
0
                nCnt |= SelectionType::ExtrudedCustomShape;
1866
0
            }
1867
1868
0
            if (svx::checkForSelectedFontWork( GetDrawView() ))
1869
0
            {
1870
0
                nCnt |= SelectionType::FontWork;
1871
0
            }
1872
0
        }
1873
1874
0
        return nCnt;
1875
0
    }
1876
1877
11.1k
    nCnt = static_cast<SelectionType>(GetCntType());
1878
1879
11.1k
    if ( IsFrameSelected() )
1880
0
    {
1881
0
        if (_rView.IsDrawMode())
1882
0
            _rView.LeaveDrawCreate();   // clean up (Bug #45639)
1883
0
        if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
1884
0
            return SelectionType::Frame;
1885
0
    }
1886
1887
11.1k
    if ( IsCursorInTable() )
1888
19
        nCnt |= SelectionType::Table;
1889
1890
11.1k
    if ( IsTableMode() )
1891
0
    {
1892
0
        nCnt |= SelectionType::Table | SelectionType::TableCell;
1893
0
        SwTable::SearchType eTableSel = GetEnhancedTableSelection();
1894
0
        if ( eTableSel == SwTable::SEARCH_ROW )
1895
0
            nCnt |= SelectionType::TableRow;
1896
0
        else if ( eTableSel == SwTable::SEARCH_COL )
1897
0
            nCnt |= SelectionType::TableCol;
1898
0
    }
1899
1900
    // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
1901
11.1k
    const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
1902
11.1k
    if ( pNumRule )
1903
763
    {
1904
763
        const SwTextNode* pTextNd =
1905
763
            sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->GetNode());
1906
1907
763
        if ( pTextNd && pTextNd->IsInList() )
1908
763
        {
1909
763
            int nLevel = pTextNd->GetActualListLevel();
1910
1911
763
            if (nLevel < 0)
1912
0
                nLevel = 0;
1913
1914
763
            if (nLevel >= MAXLEVEL)
1915
0
                nLevel = MAXLEVEL - 1;
1916
1917
763
            const SwNumFormat& rFormat = pNumRule->Get(nLevel);
1918
763
            if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
1919
27
                nCnt |= SelectionType::NumberList;
1920
763
        }
1921
763
    }
1922
1923
11.1k
    return nCnt;
1924
11.1k
}
1925
1926
bool SwWrtShell::IsSectionEditableInReadonly() const
1927
0
{
1928
0
    bool bIsEditableSect = false;
1929
0
    SwTextNode* pTextNode = GetCursor()->GetPointNode().GetTextNode();
1930
0
    if (pTextNode)
1931
0
    {
1932
0
        if (SwSectionNode* pSectNode = pTextNode->FindSectionNode())
1933
0
        {
1934
0
            bIsEditableSect = pSectNode->GetSection().IsEditInReadonly();
1935
0
        }
1936
0
    }
1937
1938
0
    return bIsEditableSect;
1939
0
}
1940
1941
// Find the text collection with the name rCollname
1942
// Returns:   Pointer at the collection or 0, if no
1943
//            text collection with this name exists, or
1944
//            this is a default template.
1945
1946
SwTextFormatColl *SwWrtShell::GetParaStyle(const UIName &rCollName, GetStyle eCreate )
1947
0
{
1948
0
    SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
1949
0
    if( !pColl && GETSTYLE_NOCREATE != eCreate )
1950
0
    {
1951
0
        SwPoolFormatId nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
1952
0
        if( SwPoolFormatId::UNKNOWN != nId || GETSTYLE_CREATEANY == eCreate )
1953
0
            pColl = GetTextCollFromPool( nId );
1954
0
    }
1955
0
    return pColl;
1956
0
}
1957
1958
// Find the text collection with the name rCollname
1959
// Returns:   Pointer at the collection or 0, if no
1960
//            character template with this name exists, or
1961
//            this is a default template or template is automatic.
1962
1963
SwCharFormat *SwWrtShell::GetCharStyle(const UIName &rFormatName, GetStyle eCreate )
1964
0
{
1965
0
    SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
1966
0
    if( !pFormat && GETSTYLE_NOCREATE != eCreate )
1967
0
    {
1968
0
        SwPoolFormatId nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
1969
0
        if( SwPoolFormatId::UNKNOWN != nId || GETSTYLE_CREATEANY == eCreate )
1970
0
            pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
1971
0
    }
1972
0
    return pFormat;
1973
0
}
1974
1975
// Find the table format with the name rFormatname
1976
// Returns:   Pointer at the collection or 0, if no
1977
//            frame format with this name exists or
1978
//            this is a default format or the format is automatic.
1979
1980
SwFrameFormat *SwWrtShell::GetTableStyle(const UIName& rFormatName)
1981
0
{
1982
0
    for( size_t i = GetTableFrameFormatCount(); i; )
1983
0
    {
1984
0
        SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
1985
0
        if( !pFormat->IsDefault() &&
1986
0
            pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
1987
0
            return pFormat;
1988
0
    }
1989
0
    return nullptr;
1990
0
}
1991
1992
273
void SwWrtShell::addCurrentPosition() {
1993
273
    SwPaM* pPaM = GetCursor();
1994
273
    m_aNavigationMgr.addEntry(*pPaM->GetPoint());
1995
273
}
1996
1997
// Applying templates
1998
1999
void SwWrtShell::SetPageStyle(const UIName &rCollName)
2000
0
{
2001
0
    if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !GetSelectedObjCount() )
2002
0
    {
2003
0
        SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
2004
0
        if( pDesc )
2005
0
            ChgCurPageDesc( *pDesc );
2006
0
    }
2007
0
}
2008
2009
// Access templates
2010
2011
UIName const & SwWrtShell::GetCurPageStyle() const
2012
0
{
2013
0
    return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
2014
0
}
2015
2016
// Change the current template referring to the existing change.
2017
2018
void SwWrtShell::QuickUpdateStyle()
2019
0
{
2020
0
    SwTextFormatColl *pColl = GetCurTextFormatColl();
2021
2022
    // Default cannot be changed
2023
0
    if(pColl && !pColl->IsDefault())
2024
0
    {
2025
0
        FillByEx(pColl);
2026
            // Also apply the template to remove hard attribute assignment.
2027
0
        SetTextFormatColl(pColl);
2028
0
    }
2029
0
}
2030
2031
void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
2032
0
{
2033
0
    SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
2034
0
    SfxItemSetFixed<
2035
0
            RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
2036
0
            RES_PARATR_BEGIN, RES_PARATR_END - 1,
2037
0
            RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
2038
0
            SID_ATTR_TABSTOP_DEFAULTS,SID_ATTR_TABSTOP_OFFSET,
2039
0
            SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
2040
0
            SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
2041
0
            SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM>  aCoreSet( GetAttrPool() );
2042
0
    GetPaMAttr( pCursor, aCoreSet );
2043
0
    bool bReset = false;
2044
2045
    // ITEM: SfxItemIter and removing SfxPoolItems:
2046
0
    std::vector<sal_uInt16> aDeleteWhichIDs;
2047
2048
0
    for (SfxItemIter aIter(aCoreSet); !aIter.IsAtEnd(); aIter.NextItem())
2049
0
    {
2050
0
        if(!IsInvalidItem(aIter.GetCurItem()))
2051
0
        {
2052
0
            if (SfxItemState::SET == aIter.GetItemState() &&
2053
0
                SfxItemState::SET == rStyleSet.GetItemState(aIter.GetCurWhich()))
2054
0
            {
2055
0
                aDeleteWhichIDs.push_back(aIter.GetCurWhich());
2056
0
                bReset = true;
2057
0
            }
2058
0
        }
2059
0
    }
2060
2061
0
    for (auto nDelWhich : aDeleteWhichIDs)
2062
0
        aCoreSet.ClearItem(nDelWhich);
2063
2064
0
    StartAction();
2065
0
    if(bReset)
2066
0
    {
2067
0
        ResetAttr({}, pCursor);
2068
0
        SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
2069
0
    }
2070
0
    mxDoc->ChgFormat(*pColl, rStyleSet );
2071
0
    EndAction();
2072
0
}
2073
2074
void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
2075
0
{
2076
0
    StartAction();
2077
2078
0
    ResetFlyFrameAttr( &rStyleSet );
2079
0
    pFormat->SetFormatAttr( rStyleSet );
2080
2081
0
    EndAction();
2082
0
}
2083
2084
void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
2085
0
{
2086
0
    ResetCursorStack();
2087
0
    if(!CanInsert())
2088
0
        return;
2089
2090
0
    bool bStarted = false;
2091
0
    SwRewriter aRewriter;
2092
2093
0
    if(HasSelection())
2094
0
    {
2095
            // Only parentheses here, because the regular insert
2096
            // is already clipped to the editshell
2097
0
        StartAllAction();
2098
2099
0
        OUString aTmpStr1 = SwResId(STR_START_QUOTE) +
2100
0
            GetSelText() +
2101
0
            SwResId(STR_END_QUOTE);
2102
0
        OUString aTmpStr3 = SwResId(STR_START_QUOTE) +
2103
0
            OUStringChar(cChar) +
2104
0
            SwResId(STR_END_QUOTE);
2105
0
        aRewriter.AddRule( UndoArg1, aTmpStr1 );
2106
0
        aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
2107
0
        aRewriter.AddRule( UndoArg3, aTmpStr3 );
2108
2109
0
        StartUndo( SwUndoId::REPLACE, &aRewriter );
2110
0
        bStarted = true;
2111
0
        DelRight(true);
2112
0
    }
2113
0
    SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
2114
2115
0
    if(bStarted)
2116
0
    {
2117
0
        EndAllAction();
2118
0
        EndUndo( SwUndoId::REPLACE, &aRewriter );
2119
0
    }
2120
0
}
2121
2122
// Some kind of controlled copy ctor
2123
2124
SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
2125
0
    : SwFEShell(rSh, _pWin)
2126
0
    , m_rView(rShell)
2127
0
    , m_aNavigationMgr(*this)
2128
0
{
2129
0
    BITFLD_INI_LIST
2130
0
    CurrShell aCurr( this );
2131
2132
0
    SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
2133
0
    SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
2134
2135
    // place the cursor on the first field...
2136
0
    Fieldmark *pBM = nullptr;
2137
0
    if (IsFormProtected() && (pBM = GetFieldmarkAfter()) !=nullptr) {
2138
0
        GotoFieldmark(pBM);
2139
0
    }
2140
0
}
2141
2142
SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
2143
                        const SwViewOption *pViewOpt )
2144
3.28k
    : SwFEShell(rDoc, _pWin, pViewOpt)
2145
3.28k
    , m_rView(rShell)
2146
3.28k
    , m_aNavigationMgr(*this)
2147
3.28k
{
2148
3.28k
    BITFLD_INI_LIST
2149
3.28k
    CurrShell aCurr( this );
2150
3.28k
    SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
2151
3.28k
    SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
2152
2153
    // place the cursor on the first field...
2154
3.28k
    Fieldmark *pBM = nullptr;
2155
3.28k
    if (IsFormProtected() && (pBM = GetFieldmarkAfter()) !=nullptr) {
2156
0
        GotoFieldmark(pBM);
2157
0
    }
2158
3.28k
}
2159
2160
SwWrtShell::~SwWrtShell()
2161
3.28k
{
2162
3.28k
    CurrShell aCurr( this );
2163
3.28k
    while(IsModePushed())
2164
0
        PopMode();
2165
3.28k
    while(PopCursor(false))
2166
0
        ;
2167
3.28k
    SwTransferable::ClearSelection( *this );
2168
3.28k
}
2169
2170
bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
2171
0
{
2172
0
    ::std::optional<SwCallLink> aLink(std::in_place, *this);
2173
0
    return Pop(eDelete, aLink);
2174
0
}
2175
2176
bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, ::std::optional<SwCallLink>& roLink)
2177
0
{
2178
0
    bool bRet = SwCursorShell::Pop(eDelete, roLink);
2179
0
    if( bRet && IsSelection() )
2180
0
    {
2181
0
        m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
2182
0
        m_fnKillSel = &SwWrtShell::ResetSelect;
2183
0
    }
2184
0
    return bRet;
2185
0
}
2186
2187
bool SwWrtShell::CanInsert()
2188
0
{
2189
0
    if(IsSelFrameMode())
2190
0
    {
2191
0
        return false;
2192
0
    }
2193
2194
0
    if(GetSelectedObjCount())
2195
0
    {
2196
0
        return false;
2197
0
    }
2198
2199
0
    if(GetView().GetDrawFuncPtr())
2200
0
    {
2201
0
        return false;
2202
0
    }
2203
2204
0
    if(GetView().GetPostItMgr()->GetActiveSidebarWin())
2205
0
    {
2206
0
        return false;
2207
0
    }
2208
2209
0
    return true;
2210
0
}
2211
2212
void SwWrtShell::ChgDBData(const SwDBData& aDBData)
2213
0
{
2214
0
    SwEditShell::ChgDBData(aDBData);
2215
    //notify the db-beamer if available
2216
0
    GetView().NotifyDBChanged();
2217
0
}
2218
2219
OUString SwWrtShell::GetSelDescr() const
2220
0
{
2221
0
    OUString aResult;
2222
2223
0
    SelectionType nSelType = GetSelectionType();
2224
0
    switch (nSelType)
2225
0
    {
2226
0
    case SelectionType::Graphic:
2227
0
        aResult = SwResId(STR_GRAPHIC);
2228
2229
0
        break;
2230
0
    case SelectionType::Frame:
2231
0
        {
2232
0
            const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
2233
2234
0
            if (pFrameFormat)
2235
0
                aResult = pFrameFormat->GetDescription();
2236
0
        }
2237
0
        break;
2238
0
    case SelectionType::DrawObject:
2239
0
        {
2240
0
            aResult = SwResId(STR_DRAWING_OBJECTS);
2241
0
        }
2242
0
        break;
2243
0
    default:
2244
0
        if (mxDoc)
2245
0
            aResult = GetCursorDescr();
2246
0
    }
2247
2248
0
    return aResult;
2249
0
}
2250
2251
void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
2252
6.82k
{
2253
6.82k
    SwFEShell::ApplyViewOptions( rOpt );
2254
    //#i115062# invalidate meta character slot
2255
6.82k
    GetView().GetViewFrame().GetBindings().Invalidate( FN_VIEW_META_CHARS );
2256
6.82k
}
2257
2258
void SwWrtShell::SetReadonlyOption(bool bSet)
2259
0
{
2260
0
    GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
2261
0
    SwViewShell::SetReadonlyOption( bSet );
2262
0
}
2263
2264
// Switch on/off header or footer of a page style - if an empty name is
2265
// given all styles are changed
2266
2267
void SwWrtShell::ChangeHeaderOrFooter(
2268
    const UIName& rStyleName, bool bHeader, bool bOn, bool bShowWarning)
2269
0
{
2270
0
    SdrView *const pSdrView = GetDrawView();
2271
0
    if (pSdrView && pSdrView->IsTextEdit())
2272
0
    {   // tdf#107474 deleting header may delete active drawing object
2273
0
        pSdrView->SdrEndTextEdit(true);
2274
0
    }
2275
0
    addCurrentPosition();
2276
0
    StartAllAction();
2277
0
    StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
2278
0
    bool bExecute = true;
2279
0
    bool bCursorSet = false;
2280
0
    for( size_t nFrom = 0, nTo = GetPageDescCnt();
2281
0
            nFrom < nTo; ++nFrom )
2282
0
    {
2283
0
        SwPageDesc aDesc( GetPageDesc( nFrom ));
2284
0
        UIName sTmp(aDesc.GetName());
2285
0
        if( rStyleName.toString().isEmpty() || rStyleName == sTmp )
2286
0
        {
2287
0
            bool bChgd = false;
2288
2289
0
            if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
2290
0
                ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
2291
0
                  (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
2292
0
            {
2293
0
                bShowWarning = false;
2294
                //Actions have to be closed while the dialog is showing
2295
0
                EndAllAction();
2296
2297
0
                weld::Window* pParent = GetView().GetFrameWeld();
2298
0
                short nResult;
2299
0
                if (bHeader) {
2300
0
                    nResult = DeleteHeaderDialog(pParent).run();
2301
0
                } else {
2302
0
                    nResult = DeleteFooterDialog(pParent).run();
2303
0
                }
2304
2305
0
                bExecute = nResult == RET_YES;
2306
0
                StartAllAction();
2307
0
                if (nResult == RET_YES)
2308
0
                    ToggleHeaderFooterEdit();
2309
0
            }
2310
0
            if( bExecute )
2311
0
            {
2312
0
                bChgd = true;
2313
0
                SwFrameFormat &rMaster = aDesc.GetMaster();
2314
0
                if(bHeader)
2315
0
                    rMaster.SetFormatAttr( SwFormatHeader( bOn ));
2316
0
                else
2317
0
                    rMaster.SetFormatAttr( SwFormatFooter( bOn ));
2318
0
                if( bOn )
2319
0
                {
2320
                    // keep in sync with FN_PGNUMBER_WIZARD
2321
0
                    constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
2322
0
                    SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm, bHeader ? constTwips_5mm : 0, RES_UL_SPACE );
2323
0
                    SwFrameFormat* pFormat = bHeader ?
2324
0
                        const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
2325
0
                        const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
2326
0
                    pFormat->SetFormatAttr( aUL );
2327
0
                    XFillStyleItem aFill(drawing::FillStyle_NONE);
2328
0
                    pFormat->SetFormatAttr(aFill);
2329
0
                }
2330
0
            }
2331
0
            if( bChgd )
2332
0
            {
2333
0
                ChgPageDesc( nFrom, aDesc );
2334
2335
0
                if( !bCursorSet && bOn )
2336
0
                {
2337
0
                    if ( !IsHeaderFooterEdit() )
2338
0
                        ToggleHeaderFooterEdit();
2339
0
                    bCursorSet = SetCursorInHdFt(
2340
0
                            rStyleName.toString().isEmpty() ? SIZE_MAX : nFrom,
2341
0
                            bHeader );
2342
0
                }
2343
0
            }
2344
0
        }
2345
0
    }
2346
0
    EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
2347
0
    EndAllAction();
2348
0
}
2349
2350
void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
2351
0
{
2352
0
    SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
2353
0
    if ( !bShow )
2354
0
        GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
2355
0
}
2356
2357
void SwWrtShell::InsertPostIt(SwFieldMgr& rFieldMgr, const SfxRequest& rReq)
2358
0
{
2359
0
    SwPostItField* pPostIt = dynamic_cast<SwPostItField*>(rFieldMgr.GetCurField());
2360
0
    bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit);
2361
0
    if (bNew || GetView().GetPostItMgr()->IsAnswer() || comphelper::LibreOfficeKit::isActive())
2362
0
    {
2363
0
        const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg(SID_ATTR_POSTIT_AUTHOR);
2364
0
        OUString sAuthor;
2365
0
        if ( pAuthorItem )
2366
0
            sAuthor = pAuthorItem->GetValue();
2367
0
        else
2368
0
        {
2369
0
            SwModule* mod = SwModule::get();
2370
0
            std::size_t nAuthor = mod->GetRedlineAuthor();
2371
0
            sAuthor = mod->GetRedlineAuthor(nAuthor);
2372
0
        }
2373
2374
0
        const SvxPostItTextItem* pTextItem = rReq.GetArg(SID_ATTR_POSTIT_TEXT);
2375
0
        OUString sText;
2376
0
        if ( pTextItem )
2377
0
            sText = pTextItem->GetValue();
2378
2379
0
        std::optional<OutlinerParaObject> oTextPara;
2380
0
        if (const SvxPostItTextItem* pHtmlItem = rReq.GetArg(SID_ATTR_POSTIT_HTML))
2381
0
        {
2382
0
            SwDocShell* pDocSh = GetView().GetDocShell();
2383
0
            Outliner aOutliner(&pDocSh->GetPool(), OutlinerMode::TextObject);
2384
0
            SwPostItHelper::ImportHTML(aOutliner, pHtmlItem->GetValue());
2385
0
            oTextPara = aOutliner.CreateParaObject();
2386
0
            sText = aOutliner.GetEditEngine().GetText();
2387
0
        }
2388
2389
        // If we have a text already registered for answer, use that
2390
0
        SwPostItMgr* pPostItMgr = GetView().GetPostItMgr();
2391
0
        if (OutlinerParaObject* pAnswer = pPostItMgr->IsAnswer())
2392
0
        {
2393
0
            if (!pPostItMgr->GetAnswerText().isEmpty())
2394
0
            {
2395
0
                sText = GetView().GetPostItMgr()->GetAnswerText();
2396
0
                pPostItMgr->RegisterAnswerText(OUString());
2397
0
            }
2398
0
            const EditTextObject& rTextObject = pAnswer->GetTextObject();
2399
0
            if (rTextObject.GetParagraphCount() != 1 || !rTextObject.GetText(0).isEmpty())
2400
0
            {
2401
0
                oTextPara = *pAnswer;
2402
0
                sText = rTextObject.GetText();
2403
0
            }
2404
0
        }
2405
2406
0
        if ( HasSelection() && !IsTableMode() )
2407
0
        {
2408
0
            KillPams();
2409
0
        }
2410
2411
        // #i120513# Inserting a comment into an autocompletion crashes
2412
        // --> suggestion has to be removed before
2413
0
        GetView().GetEditWin().StopQuickHelp();
2414
2415
0
        SwInsertField_Data aData(SwFieldTypesEnum::Postit, 0, sAuthor, sText, 0);
2416
2417
0
        {
2418
0
            SvxPostItIdItem const*const pParentParaIdItem{rReq.GetArg(SID_ATTR_POSTIT_PARENTPARAID)};
2419
0
            SvxPostItIdItem const*const pParentPostItIdItem{rReq.GetArg(SID_ATTR_POSTIT_PARENTPOSTITID)};
2420
0
            SfxStringItem const*const pParentNameItem{rReq.GetArg(SID_ATTR_POSTIT_PARENTNAME)};
2421
0
            if (pParentParaIdItem && pParentPostItIdItem && pParentNameItem)
2422
0
            {
2423
0
                aData.m_oParentId.emplace(pParentParaIdItem->GetValue().toUInt32(),
2424
0
                    pParentPostItIdItem->GetValue().toUInt32(),
2425
0
                    pParentNameItem->GetValue());
2426
0
            }
2427
0
        }
2428
2429
0
        if (IsSelFrameMode())
2430
0
        {
2431
0
            SwFlyFrame* pFly = GetSelectedFlyFrame();
2432
2433
            // Remember the anchor of the selected object before deletion.
2434
0
            std::optional<SwPosition> oAnchor;
2435
0
            if (pFly)
2436
0
            {
2437
0
                SwFrameFormat* pFormat = pFly->GetFormat();
2438
0
                if (pFormat)
2439
0
                {
2440
0
                    RndStdIds eAnchorId = pFormat->GetAnchor().GetAnchorId();
2441
0
                    if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR) && pFormat->GetAnchor().GetAnchorNode())
2442
0
                    {
2443
0
                        oAnchor.emplace(*pFormat->GetAnchor().GetContentAnchor());
2444
0
                    }
2445
0
                }
2446
0
            }
2447
2448
            // A frame is selected, end frame selection.
2449
0
            EnterStdMode();
2450
0
            GetView().AttrChangedNotify(nullptr);
2451
2452
            // Set up text selection, so the anchor of the frame will be the anchor of the
2453
            // comment.
2454
0
            if (pFly)
2455
0
            {
2456
0
                if (oAnchor)
2457
0
                    *GetCurrentShellCursor().GetPoint() = *oAnchor;
2458
0
                SwFrameFormat* pFormat = pFly->GetFormat();
2459
0
                if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
2460
0
                {
2461
0
                    Right(SwCursorSkipMode::Cells, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true);
2462
0
                }
2463
0
                else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR)
2464
0
                {
2465
0
                    aData.m_oAnnotationRange.emplace(*GetCurrentShellCursor().Start(),
2466
0
                                                     *GetCurrentShellCursor().End());
2467
0
                }
2468
0
            }
2469
0
        }
2470
2471
        // Defer broadcast of postit field update from layout until oTextPara has been
2472
        // applied to the field's associated postit window
2473
0
        if (oTextPara)
2474
0
            StartAction();
2475
2476
0
        rFieldMgr.InsertField( aData );
2477
2478
0
        Push();
2479
0
        SwCursorShell::Left(1, SwCursorSkipMode::Chars);
2480
0
        pPostIt = static_cast<SwPostItField*>(rFieldMgr.GetCurField());
2481
2482
0
        if (pPostIt && oTextPara)
2483
0
            pPostIt->SetTextObject(*oTextPara);
2484
2485
0
        Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
2486
2487
0
        if (oTextPara)
2488
0
            EndAction();
2489
0
    }
2490
2491
    // Client has disabled annotations rendering, no need to
2492
    // focus the postit field
2493
0
    if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations())
2494
0
        return;
2495
2496
0
    if (pPostIt)
2497
0
    {
2498
0
        SwFieldType* pType = GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
2499
0
        if(auto pFormat = pType->FindFormatForField(pPostIt))
2500
0
            pFormat->Broadcast( SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::FOCUS, &GetView() ) );
2501
0
    }
2502
0
}
2503
2504
bool SwWrtShell::IsOutlineContentVisible(const size_t nPos)
2505
0
{
2506
0
    const SwOutlineNodes& rOutlineNodes = GetDoc()->GetNodes().GetOutLineNds();
2507
0
    const SwNode* pOutlineNode = rOutlineNodes[nPos];
2508
2509
    // no layout frame means outline folding is set to include sub levels and the outline node has
2510
    // a parent outline node with outline content visible attribute false (folded outline content)
2511
0
    if (!pOutlineNode->GetTextNode()->getLayoutFrame(GetLayout()))
2512
0
        return false;
2513
2514
    // try the next node to determine if this outline node has visible content
2515
0
    SwNodeIndex aIdx(*pOutlineNode, +1);
2516
0
    if (aIdx.GetNode() == aIdx.GetNodes().GetEndOfContent()) // end of regular content
2517
0
        return false;
2518
2519
0
    if (aIdx.GetNode().IsTextNode() || aIdx.GetNode().IsTableNode() ||
2520
0
            aIdx.GetNode().IsSectionNode())
2521
0
    {
2522
        // * sublevels treated as outline content
2523
        //     If next node (aIdx) doesn't have a layout frame
2524
        //     then this outline node does not have visible outline content.
2525
        // * sublevels NOT treated as outline content
2526
        //     If the next node (aIdx) is the next outline node
2527
        //     then return the outline content visible attribute value.
2528
0
        if (!GetViewOptions()->IsTreatSubOutlineLevelsAsContent() &&
2529
0
                nPos + 1 < rOutlineNodes.size() &&
2530
0
                rOutlineNodes[nPos + 1] == &aIdx.GetNode())
2531
0
            return GetAttrOutlineContentVisible(nPos);
2532
2533
0
        if (aIdx.GetNode().IsTextNode())
2534
0
            return aIdx.GetNode().GetTextNode()->getLayoutFrame(GetLayout());
2535
0
        if (aIdx.GetNode().IsTableNode())
2536
0
        {
2537
0
            SwTable& rTable = aIdx.GetNode().GetTableNode()->GetTable();
2538
0
            return rTable.HasLayout();
2539
0
        }
2540
0
        if (aIdx.GetNode().IsSectionNode())
2541
0
        {
2542
0
            const auto pFormat = aIdx.GetNode().GetSectionNode()->GetSection().GetFormat();
2543
0
            return pFormat && pFormat->IsVisible();
2544
0
        }
2545
0
    }
2546
2547
0
    return true;
2548
0
}
2549
2550
void SwWrtShell::MakeOutlineLevelsVisible(const int nLevel)
2551
0
{
2552
0
    MakeAllOutlineContentTemporarilyVisible a(GetDoc());
2553
2554
0
    m_rView.SetMaxOutlineLevelShown(nLevel);
2555
2556
0
    bool bDocChanged = false;
2557
2558
0
    const SwOutlineNodes& rOutlineNodes = GetNodes().GetOutLineNds();
2559
2560
    // Make all missing frames.
2561
0
    for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
2562
0
    {
2563
0
        SwNode* pNode = rOutlineNodes[nPos];
2564
0
        if (!pNode->GetTextNode()->getLayoutFrame(GetLayout()))
2565
0
        {
2566
0
            SwNodeIndex aIdx(*pNode, +1);
2567
            // Make the outline paragraph frame
2568
0
            ::MakeFrames(*GetDoc(), *pNode, aIdx.GetNode(), true);
2569
            // Make the outline content visible but don't set the outline visible attribute and
2570
            // don't make outline content made visible not visible that have outline visible
2571
            // attribute false. Visibility will be taken care of when
2572
            // MakeAllOutlineContentTemporarilyVisible goes out of scope.
2573
0
            MakeOutlineContentVisible(nPos, true, false);
2574
0
            bDocChanged = true;
2575
0
        }
2576
0
    }
2577
    // Remove outline paragraph frame and outline content frames above given level.
2578
0
    for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNodes.size(); ++nPos)
2579
0
    {
2580
0
        SwNode* pNode = rOutlineNodes[nPos];
2581
0
        auto nOutlineLevel = pNode->GetTextNode()->GetAttrOutlineLevel();
2582
0
        if (nOutlineLevel > nLevel)
2583
0
        {
2584
            // Remove the outline content but don't set the outline visible attribute. Visibility
2585
            // will be taken care of when MakeAllOutlineContentTemporarilyVisible goes out of scope.
2586
0
            MakeOutlineContentVisible(nPos, false, false);
2587
            // Remove the outline paragraph frame.
2588
0
            pNode->GetTextNode()->DelFrames(GetLayout());
2589
0
            bDocChanged = true;
2590
0
        }
2591
0
    }
2592
2593
    // Broadcast DocChanged if document layout has changed so the Navigator will be updated.
2594
0
    if (bDocChanged)
2595
0
        GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
2596
0
}
2597
2598
void SwWrtShell::MakeOutlineContentVisible(const size_t nPos, bool bMakeVisible, bool bSetAttrOutlineVisibility)
2599
0
{
2600
0
    const SwNodes& rNodes = GetNodes();
2601
0
    const SwOutlineNodes& rOutlineNodes = rNodes.GetOutLineNds();
2602
2603
0
    SwNode* pSttNd = rOutlineNodes[nPos];
2604
2605
    // determine end node
2606
0
    SwNode* pEndNd = &rNodes.GetEndOfContent();
2607
0
    if (rOutlineNodes.size() > nPos + 1)
2608
0
        pEndNd = rOutlineNodes[nPos + 1];
2609
2610
0
    if (GetViewOptions()->IsTreatSubOutlineLevelsAsContent())
2611
0
    {
2612
        // get the last outline node to include (iPos)
2613
0
        int nLevel = pSttNd->GetTextNode()->GetAttrOutlineLevel();
2614
0
        int nMaxOutlineLevelShown = m_rView.GetMaxOutlineLevelShown();
2615
0
        SwOutlineNodes::size_type iPos = nPos;
2616
0
        while (++iPos < rOutlineNodes.size() &&
2617
0
               rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() > nLevel &&
2618
0
               rOutlineNodes[iPos]->GetTextNode()->GetAttrOutlineLevel() <= nMaxOutlineLevelShown);
2619
2620
        // get the correct end node
2621
        // the outline node may be in frames, headers, footers special section of doc model
2622
0
        SwNode* pStartOfSectionNodeSttNd = pSttNd->StartOfSectionNode();
2623
0
        while (pStartOfSectionNodeSttNd->StartOfSectionNode()
2624
0
               != pStartOfSectionNodeSttNd->StartOfSectionNode()->StartOfSectionNode())
2625
0
        {
2626
0
            pStartOfSectionNodeSttNd = pStartOfSectionNodeSttNd->StartOfSectionNode();
2627
0
        }
2628
0
        pEndNd = pStartOfSectionNodeSttNd->EndOfSectionNode();
2629
2630
0
        if (iPos < rOutlineNodes.size())
2631
0
        {
2632
0
            SwNode* pStartOfSectionNode = rOutlineNodes[iPos]->StartOfSectionNode();
2633
0
            while (pStartOfSectionNode->StartOfSectionNode()
2634
0
                   != pStartOfSectionNode->StartOfSectionNode()->StartOfSectionNode())
2635
0
            {
2636
0
                pStartOfSectionNode = pStartOfSectionNode->StartOfSectionNode();
2637
0
            }
2638
0
            if (pStartOfSectionNodeSttNd == pStartOfSectionNode)
2639
0
                pEndNd = rOutlineNodes[iPos];
2640
0
        }
2641
0
    }
2642
2643
    // table, text box, header, footer
2644
0
    if (pSttNd->GetTableBox() || pSttNd->GetIndex() < rNodes.GetEndOfExtras().GetIndex())
2645
0
    {
2646
        // limit to within section
2647
0
        if (pSttNd->EndOfSectionIndex() < pEndNd->GetIndex())
2648
0
            pEndNd = pSttNd->EndOfSectionNode();
2649
0
    }
2650
    // if pSttNd isn't in table but pEndNd is, skip over all outline nodes in table
2651
0
    else if (pEndNd->GetTableBox())
2652
0
    {
2653
0
        pEndNd = &rNodes.GetEndOfContent();
2654
0
        for (size_t nOutlinePos = nPos + 2; nOutlinePos < rOutlineNodes.size(); nOutlinePos++)
2655
0
        {
2656
0
            if (!(rOutlineNodes[nOutlinePos]->GetTableBox()))
2657
0
            {
2658
0
                pEndNd = rOutlineNodes[nOutlinePos];
2659
0
                break;
2660
0
            }
2661
0
        }
2662
0
    }
2663
    // end node determined
2664
2665
    // Remove content frames from the next node after the starting outline node to
2666
    // the determined ending node. Always do this to prevent the chance of duplicate
2667
    // frames being made. They will be remade below if needed.
2668
0
    SwNodeIndex aIdx(*pSttNd, +1);
2669
0
    while (aIdx != *pEndNd)
2670
0
    {
2671
0
        SwNode* pNd = &aIdx.GetNode();
2672
0
        if (pNd->IsContentNode())
2673
0
            pNd->GetContentNode()->DelFrames(nullptr);
2674
0
        else if (pNd->IsTableNode())
2675
0
            pNd->GetTableNode()->DelFrames(nullptr);
2676
0
        ++aIdx;
2677
0
    }
2678
2679
0
    if (bMakeVisible) // make outline nodes outline content visible
2680
0
    {
2681
        // reset the index marker and make frames
2682
0
        aIdx.Assign(*pSttNd, +1);
2683
0
        ::MakeFrames(*GetDoc(), aIdx.GetNode(), *pEndNd, true);
2684
2685
0
        if (bSetAttrOutlineVisibility)
2686
0
        {
2687
0
            pSttNd->GetTextNode()->SetAttrOutlineContentVisible(true);
2688
2689
            // make outline content made visible that have outline visible attribute false not visible
2690
0
            while (aIdx != *pEndNd)
2691
0
            {
2692
0
                SwNode* pNd = &aIdx.GetNode();
2693
0
                if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
2694
0
                {
2695
0
                    SwTextNode* pTextNd = pNd->GetTextNode();
2696
0
                    if (!pTextNd->GetAttrOutlineContentVisible())
2697
0
                    {
2698
0
                        SwOutlineNodes::size_type iPos;
2699
0
                        if (rOutlineNodes.Seek_Entry(pTextNd, &iPos))
2700
0
                        {
2701
0
                            if (pTextNd->getLayoutFrame(nullptr))
2702
0
                                MakeOutlineContentVisible(iPos, false);
2703
0
                        }
2704
0
                    }
2705
0
                }
2706
0
                ++aIdx;
2707
0
            }
2708
0
        }
2709
0
    }
2710
0
    else if (bSetAttrOutlineVisibility)
2711
0
        pSttNd->GetTextNode()->SetAttrOutlineContentVisible(false);
2712
0
}
2713
2714
// make content visible or not visible only if needed
2715
void SwWrtShell::InvalidateOutlineContentVisibility()
2716
0
{
2717
    // tdf#170599 fix taken from fix for:
2718
    //   "rhbz#818557, fdo#58893: EndAllAction will call SelectShell(),
2719
    //    which pushes a bunch of SfxShells that are not cleared
2720
    //    (for unknown reasons) when closing the document, causing crash;
2721
    //    setting g_bNoInterrupt appears to avoid the problem."
2722
    // In this case the crash occurs when reopening Print Preview with outline folding enabled and
2723
    // a heading in the first paragraph and display formatting hidden characters option is enabled.
2724
0
    comphelper::FlagRestorationGuard g(g_bNoInterrupt, true);
2725
2726
0
    StartAction();
2727
2728
0
    GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
2729
2730
0
    const SwOutlineNodes& rOutlineNds = GetNodes().GetOutLineNds();
2731
0
    for (SwOutlineNodes::size_type nPos = 0; nPos < rOutlineNds.size(); ++nPos)
2732
0
    {
2733
0
        bool bIsOutlineContentVisible = IsOutlineContentVisible(nPos);
2734
0
        bool bOutlineContentVisibleAttr = rOutlineNds[nPos]->GetTextNode()->GetAttrOutlineContentVisible();
2735
0
        if (!bIsOutlineContentVisible && bOutlineContentVisibleAttr)
2736
0
            MakeOutlineContentVisible(nPos);
2737
0
        else if (bIsOutlineContentVisible && !bOutlineContentVisibleAttr)
2738
0
            MakeOutlineContentVisible(nPos, false);
2739
0
    }
2740
2741
0
    EndAction();
2742
0
}
2743
2744
void SwWrtShell::MakeAllFoldedOutlineContentVisible(bool bMakeVisible)
2745
0
{
2746
0
    if (bMakeVisible)
2747
0
    {
2748
        // make all content visible
2749
2750
        // When shortcut is assigned to the show outline content visibility button and used to
2751
        // toggle the feature and the mouse pointer is on an outline frame the button will not
2752
        // be removed. An easy way to make sure the button does not remain shown is to use the
2753
        // HideControls function.
2754
0
        GetView().GetEditWin().GetFrameControlsManager().HideControls(FrameControlType::Outline);
2755
2756
        // temporarily set outline content visible attribute true for folded outline nodes
2757
0
        std::vector<SwNode*> aFoldedOutlineNodeArray;
2758
0
        for (SwNode* pNd: GetNodes().GetOutLineNds())
2759
0
        {
2760
0
            if (!pNd->GetTextNode()->GetAttrOutlineContentVisible())
2761
0
            {
2762
0
                aFoldedOutlineNodeArray.push_back(pNd);
2763
0
                pNd->GetTextNode()->SetAttrOutlineContentVisible(true);
2764
0
            }
2765
0
        }
2766
2767
0
        InvalidateOutlineContentVisibility();
2768
2769
        // restore outline content visible attribute for folded outline nodes
2770
0
        for (SwNode* pNd: aFoldedOutlineNodeArray)
2771
0
            pNd->GetTextNode()->SetAttrOutlineContentVisible(false);
2772
0
    }
2773
0
    else
2774
0
    {
2775
0
        AssureStdMode();
2776
2777
        // Get the outline position of the cursor so the cursor can be place at a visible outline
2778
        // node if it is not visible after InvalidateOutlineContentVisiblity below.
2779
0
        SwOutlineNodes::size_type nPos = GetOutlinePos();
2780
2781
0
        InvalidateOutlineContentVisibility();
2782
2783
        // If needed, find a visible outline node to place the cursor.
2784
0
        if (nPos != SwOutlineNodes::npos && !IsOutlineContentVisible(nPos))
2785
0
        {
2786
0
            while (nPos != SwOutlineNodes::npos &&
2787
0
                   !GetNodes().GetOutLineNds()[nPos]->GetTextNode()->getLayoutFrame(GetLayout()))
2788
0
                --nPos;
2789
0
            if (nPos != SwOutlineNodes::npos)
2790
0
                GotoOutline(nPos);
2791
0
        }
2792
0
    }
2793
0
    GetView().GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
2794
0
}
2795
2796
bool SwWrtShell::GetAttrOutlineContentVisible(const size_t nPos) const
2797
0
{
2798
0
    return GetNodes().GetOutLineNds()[nPos]->GetTextNode()->GetAttrOutlineContentVisible();
2799
0
}
2800
2801
bool SwWrtShell::HasFoldedOutlineContentSelected() const
2802
0
{
2803
    // No need to check for selection over folded outline content when there are no outline nodes.
2804
0
    if (GetDoc()->GetNodes().GetOutLineNds().empty())
2805
0
        return false;
2806
0
    for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
2807
0
    {
2808
0
        SwPaM aPaM(*rPaM.GetMark(), *rPaM.GetPoint());
2809
0
        aPaM.Normalize();
2810
0
        SwNodeIndex aPointIdx(aPaM.GetPoint()->GetNode());
2811
0
        SwNodeIndex aMarkIdx(aPaM.GetMark()->GetNode());
2812
        // Prevent crash in the for loop below by adjusting the mark if it is set to the end of
2813
        // content node.
2814
0
        if (aMarkIdx.GetNode() == GetDoc()->GetNodes().GetEndOfContent())
2815
0
            --aMarkIdx;
2816
0
        if (aPointIdx == aMarkIdx)
2817
0
            continue;
2818
        // Return true if any nodes in PaM are folded outline content nodes.
2819
0
        SwOutlineNodes::size_type nPos;
2820
0
        for (SwNodeIndex aIdx = aPointIdx; aIdx <= aMarkIdx; ++aIdx)
2821
0
        {
2822
            // To allow delete when the start of the selection is at the start of a
2823
            // paragraph and the end of the selection is at the start of a paragraph and there
2824
            // are no folded outline content nodes in between.
2825
0
            if (aIdx == aMarkIdx && aPaM.GetPoint()->GetContentIndex() == 0 &&
2826
0
                    aPaM.GetMark()->GetContentIndex() == 0)
2827
0
                return false;
2828
2829
0
            if (GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(&(aIdx.GetNode()), &nPos) &&
2830
0
                    !GetAttrOutlineContentVisible(nPos))
2831
0
                return true;
2832
0
        }
2833
0
    }
2834
0
    return false;
2835
0
}
2836
2837
void SwWrtShell::InfoReadOnlyDialog(bool bAsync) const
2838
0
{
2839
#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16
2840
#pragma GCC diagnostic push
2841
#pragma GCC diagnostic ignored "-Warray-bounds"
2842
#endif
2843
0
    if (bAsync)
2844
0
    {
2845
0
        auto xInfo = std::make_shared<weld::MessageDialogController>(
2846
0
                    GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog");
2847
0
        if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
2848
0
                HasFoldedOutlineContentSelected())
2849
0
        {
2850
0
            xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2851
0
            xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2852
0
        }
2853
0
        weld::DialogController::runAsync(xInfo, [](int) {});
2854
0
    }
2855
0
    else
2856
0
    {
2857
0
        std::unique_ptr<weld::Builder>
2858
0
                xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(),
2859
0
                                                    u"modules/swriter/ui/inforeadonlydialog.ui"_ustr));
2860
0
        std::unique_ptr<weld::MessageDialog>
2861
0
                xInfo(xBuilder->weld_message_dialog(u"InfoReadonlyDialog"_ustr));
2862
0
        if (GetViewOptions()->IsShowOutlineContentVisibilityButton() &&
2863
0
                HasFoldedOutlineContentSelected())
2864
0
        {
2865
0
            xInfo->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2866
0
            xInfo->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2867
0
        }
2868
0
        xInfo->run();
2869
0
    }
2870
#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 16
2871
#pragma GCC diagnostic pop
2872
#endif
2873
0
}
2874
2875
bool SwWrtShell::WarnHiddenSectionDialog() const
2876
0
{
2877
0
    std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
2878
0
        GetView().GetFrameWeld(), u"modules/swriter/ui/warnhiddensectiondialog.ui"_ustr));
2879
0
    std::unique_ptr<weld::MessageDialog> xQuery(
2880
0
        xBuilder->weld_message_dialog(u"WarnHiddenSectionDialog"_ustr));
2881
0
    if (GetViewOptions()->IsShowOutlineContentVisibilityButton()
2882
0
        && HasFoldedOutlineContentSelected())
2883
0
    {
2884
0
        xQuery->set_primary_text(SwResId(STR_INFORODLG_FOLDED_PRIMARY));
2885
0
        xQuery->set_secondary_text(SwResId(STR_INFORODLG_FOLDED_SECONDARY));
2886
0
    }
2887
2888
0
    return (RET_YES == xQuery->run());
2889
0
}
2890
2891
bool SwWrtShell::WarnSwitchToDesignModeDialog() const
2892
0
{
2893
0
    std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(nullptr,
2894
0
        VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_A11Y_DESIGN_MODE_PRIMARY)));
2895
0
    xQuery->set_default_response(RET_YES);
2896
0
    xQuery->set_title(SwResId(STR_A11Y_DESIGN_MODE_TITLE));
2897
0
    xQuery->set_secondary_text(SwResId(STR_A11Y_DESIGN_MODE_SECONDARY));
2898
2899
0
    return (RET_YES == xQuery->run());
2900
0
}
2901
2902
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */