Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/sw/source/uibase/wrtsh/delete.cxx
Line
Count
Source (jump to first uncovered line)
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 <hintids.hxx>
21
#include <wrtsh.hxx>
22
#include <swcrsr.hxx>
23
#include <editeng/lrspitem.hxx>
24
#include <view.hxx>
25
#include <drawbase.hxx>
26
#include <unobaseclass.hxx>
27
#include <fmtanchr.hxx>
28
#include <flyfrm.hxx>
29
#include <ndtxt.hxx>
30
#include <txtfld.hxx>
31
#include <docufld.hxx>
32
#include <IDocumentUndoRedo.hxx>
33
#include <i18nutil/unicode.hxx>
34
#include <o3tl/temporary.hxx>
35
#include <rtl/character.hxx>
36
#include <osl/diagnose.h>
37
#include <doc.hxx>
38
#include <IDocumentRedlineAccess.hxx>
39
#include <IDocumentLayoutAccess.hxx>
40
#include <txtfrm.hxx>
41
42
inline void SwWrtShell::OpenMark()
43
0
{
44
0
    StartAllAction();
45
0
    ResetCursorStack();
46
0
    KillPams();
47
0
    SetMark();
48
0
}
49
50
inline void SwWrtShell::CloseMark( bool bOkFlag )
51
0
{
52
0
    if( bOkFlag )
53
0
        UpdateAttr();
54
0
    else
55
0
        SwapPam();
56
57
0
    ClearMark();
58
0
    EndAllAction();
59
0
}
60
61
62
63
// #i23725#
64
bool SwWrtShell::TryRemoveIndent()
65
0
{
66
0
    bool bResult = false;
67
68
0
    SfxItemSetFixed<RES_MARGIN_FIRSTLINE, RES_MARGIN_TEXTLEFT> aAttrSet(GetAttrPool());
69
0
    GetCurAttr(aAttrSet);
70
71
0
    SvxFirstLineIndentItem firstLine(aAttrSet.Get(RES_MARGIN_FIRSTLINE));
72
0
    SvxTextLeftMarginItem leftMargin(aAttrSet.Get(RES_MARGIN_TEXTLEFT));
73
0
    short aOldFirstLineOfst = firstLine.ResolveTextFirstLineOffset({});
74
75
0
    if (aOldFirstLineOfst > 0)
76
0
    {
77
0
        firstLine.SetTextFirstLineOffset(SvxIndentValue::zero());
78
0
        bResult = true;
79
0
    }
80
0
    else if (aOldFirstLineOfst < 0)
81
0
    {
82
        // this used to call SetLeft() but this should be the same result
83
0
        firstLine.SetTextFirstLineOffset(SvxIndentValue::zero());
84
0
        leftMargin.SetTextLeft(
85
0
            SvxIndentValue::twips(leftMargin.ResolveTextLeft({}) + aOldFirstLineOfst));
86
0
        bResult = true;
87
0
    }
88
0
    else if (leftMargin.GetTextLeft().m_dValue != 0.0)
89
0
    {
90
0
        leftMargin.SetTextLeft(SvxIndentValue::zero());
91
0
        bResult = true;
92
0
    }
93
94
0
    if (bResult)
95
0
    {
96
0
        aAttrSet.Put(firstLine);
97
0
        aAttrSet.Put(leftMargin);
98
0
        SetAttrSet(aAttrSet);
99
0
    }
100
101
0
    return bResult;
102
0
}
103
104
/** Description: Erase the line. */
105
106
void SwWrtShell::DelLine()
107
0
{
108
0
    SwActContext aActContext(this);
109
0
    ResetCursorStack();
110
        // remember the old cursor
111
0
    Push();
112
0
    ClearMark();
113
0
    SwCursorShell::LeftMargin();
114
0
    SetMark();
115
0
    SwCursorShell::RightMargin();
116
117
0
    bool bRet = Delete(false);
118
0
    Pop(SwCursorShell::PopMode::DeleteCurrent);
119
0
    if( bRet )
120
0
        UpdateAttr();
121
0
}
122
123
void SwWrtShell::DelToStartOfLine()
124
0
{
125
0
    OpenMark();
126
0
    SwCursorShell::LeftMargin();
127
0
    bool bRet = Delete(false);
128
0
    CloseMark( bRet );
129
0
}
130
131
void SwWrtShell::DelToEndOfLine()
132
0
{
133
0
    OpenMark();
134
0
    SwCursorShell::RightMargin();
135
0
    bool bRet = Delete(false);
136
0
    CloseMark( bRet );
137
0
}
138
139
bool SwWrtShell::DelLeft()
140
0
{
141
    // If it's a Fly, throw it away
142
0
    SelectionType nSelType = GetSelectionType();
143
0
    const SelectionType nCmp = SelectionType::Frame | SelectionType::Graphic | SelectionType::Ole | SelectionType::DrawObject;
144
0
    if( nCmp & nSelType )
145
0
    {
146
        // #108205# Remember object's position.
147
0
        Point aTmpPt = GetObjRect().TopLeft();
148
149
0
        DelSelectedObj();
150
151
        // #108205# Set cursor to remembered position.
152
0
        SetCursor(&aTmpPt);
153
154
0
        LeaveSelFrameMode();
155
0
        UnSelectFrame();
156
157
0
        nSelType = GetSelectionType();
158
0
        if ( nCmp & nSelType )
159
0
        {
160
0
            EnterSelFrameMode();
161
0
            GotoNextFly();
162
0
        }
163
164
0
        return true;
165
0
    }
166
167
    // If a selection exists, erase this
168
0
    if ( IsSelection() )
169
0
    {
170
0
        if( !IsBlockMode() || HasSelection() )
171
0
        {
172
            //OS: Once again Basic: SwActContext must be leaved
173
            //before EnterStdMode!
174
0
            {
175
0
                SwActContext aActContext(this);
176
0
                ResetCursorStack();
177
0
                Delete(false, true);
178
0
                UpdateAttr();
179
0
            }
180
0
            if( IsBlockMode() )
181
0
            {
182
0
                NormalizePam();
183
0
                ClearMark();
184
0
                EnterBlockMode();
185
0
            }
186
0
            else
187
0
                EnterStdMode();
188
0
            return true;
189
0
        }
190
0
        else
191
0
            EnterStdMode();
192
0
    }
193
194
    // JP 29.06.95: never erase a table standing in front of it.
195
0
    bool bSwap = false;
196
0
    const SwTableNode * pWasInTableNd = SwCursorShell::IsCursorInTable();
197
198
0
    if( SwCursorShell::IsSttPara())
199
0
    {
200
        // Start/EndAllAction to avoid cursor flickering
201
0
        UnoActionContext c(GetDoc());
202
0
        SwCursorShell::Push();
203
204
        // #i4032# Don't actually call a 'delete' if we
205
        // changed the table cell, compare DelRight().
206
0
        const SwStartNode * pSNdOld = pWasInTableNd ?
207
0
                                      GetCursor()->GetPointNode().FindTableBoxStartNode() :
208
0
                                      nullptr;
209
210
        // If the cursor is at the beginning of a paragraph, try to step
211
        // backwards. On failure we are done.
212
0
        bool bDoSomething = SwCursorShell::Left(1,SwCursorSkipMode::Chars);
213
214
0
        if (bDoSomething)
215
0
        {
216
            // If the cursor entered or left a table (or both) we are done.
217
0
            const SwTableNode* pIsInTableNd = SwCursorShell::IsCursorInTable();
218
0
            bDoSomething = pIsInTableNd == pWasInTableNd;
219
220
0
            if (bDoSomething)
221
0
            {
222
0
                const SwStartNode* pSNdNew = pIsInTableNd ?
223
0
                    GetCursor()->GetPointNode().FindTableBoxStartNode() :
224
0
                    nullptr;
225
226
                // #i4032# Don't actually call a 'delete' if we
227
                // changed the table cell, compare DelRight().
228
0
                bDoSomething = pSNdOld == pSNdNew;
229
0
            }
230
0
        }
231
232
0
        if (!bDoSomething)
233
0
        {
234
            // tdf#115132 Restore previous position and we are done
235
0
            SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
236
0
            return false;
237
0
        }
238
239
0
        SwCursorShell::Pop(SwCursorShell::PopMode::DeleteStack);
240
241
0
        OpenMark();
242
0
        SwCursorShell::Right(1,SwCursorSkipMode::Chars);
243
0
        SwCursorShell::SwapPam();
244
0
        bSwap = true;
245
0
    }
246
0
    else
247
0
    {
248
        // If we are just to the right to a fieldmark, then remove it completely
249
0
        const SwPosition* pCurPos = GetCursor()->GetPoint();
250
0
        SwPosition aPrevChar(*pCurPos->GetContentNode(), pCurPos->GetContentIndex() - 1);
251
0
        sw::mark::Fieldmark* pFm = getIDocumentMarkAccess()->getFieldmarkAt(aPrevChar);
252
0
        if (pFm && pFm->GetMarkEnd() == *pCurPos)
253
0
        {
254
0
            mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
255
0
            IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm);
256
0
            getIDocumentMarkAccess()->deleteMark(pFm);
257
0
            mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
258
0
            return true;
259
0
        }
260
261
0
        OpenMark();
262
0
        SwCursorShell::Left(1, SwCursorSkipMode::Chars);
263
264
        // If we are deleting a variation selector, we want to delete the
265
        // whole sequence.
266
0
        sal_uInt32 nCode = GetChar(false);
267
0
        if ( rtl::isSurrogate( nCode ) )
268
0
        {
269
0
            OUString sStr = GetSelText();
270
0
            nCode = sStr.iterateCodePoints( &o3tl::temporary(sal_Int32(0)) );
271
0
        }
272
273
0
        if ( unicode::isVariationSelector( nCode ) )
274
0
        {
275
0
            SwCursorShell::Push();
276
0
            SwCursorShell::Left(1, SwCursorSkipMode::Chars);
277
0
            SwCursorShell::Pop( SwCursorShell::PopMode::DeleteStack );
278
0
        }
279
0
    }
280
0
    bool bRet = Delete(true, true);
281
0
    if( !bRet && bSwap )
282
0
        SwCursorShell::SwapPam();
283
0
    CloseMark( bRet );
284
285
0
    return bRet;
286
0
}
287
288
bool SwWrtShell::DelRight(bool const isReplaceHeuristic)
289
0
{
290
        // Will be or'ed, if a tableselection exists;
291
        // will here be implemented on SelectionType::Table
292
0
    bool bRet = false;
293
0
    SelectionType nSelection = GetSelectionType();
294
0
    if(nSelection & SelectionType::TableCell)
295
0
        nSelection = SelectionType::Table;
296
0
    if(nSelection & SelectionType::Text)
297
0
        nSelection = SelectionType::Text;
298
299
0
    switch( nSelection & ~SelectionType::Ornament & ~SelectionType::Media )
300
0
    {
301
0
    case SelectionType::PostIt:
302
0
    case SelectionType::Text:
303
0
    case SelectionType::Table:
304
0
    case SelectionType::NumberList:
305
            //  If a selection exists, erase it.
306
0
        if( IsSelection() )
307
0
        {
308
0
            if( !IsBlockMode() || HasSelection() )
309
0
            {
310
                //OS: And once again Basic: SwActContext must be
311
                //leaved before EnterStdMode !
312
0
                {
313
0
                    SwActContext aActContext(this);
314
0
                    ResetCursorStack();
315
0
                    Delete(isReplaceHeuristic);
316
0
                    UpdateAttr();
317
0
                }
318
0
                if( IsBlockMode() )
319
0
                {
320
0
                    NormalizePam();
321
0
                    ClearMark();
322
0
                    EnterBlockMode();
323
0
                }
324
0
                else
325
0
                    EnterStdMode();
326
0
                bRet = true;
327
0
                break;
328
0
            }
329
0
            else
330
0
                EnterStdMode();
331
0
        }
332
333
0
        if (SwCursorShell::IsEndPara())
334
0
        {
335
            // Start/EndAllAction to avoid cursor flickering
336
0
            UnoActionContext c(GetDoc());
337
338
0
            const SwTableNode* pWasInTableNd = IsCursorInTable();
339
            // #108049# Save the startnode of the current cell
340
0
            const SwStartNode* pSNdOld = pWasInTableNd ?
341
0
                GetCursor()->GetPointNode().FindTableBoxStartNode() : nullptr;
342
0
            SwTextNode* pOldTextNode = GetCursor()->GetPointNode().GetTextNode();
343
0
            bool bCheckDelFull = SelectionType::Text & nSelection && SwCursorShell::IsSttPara();
344
0
            bool bDelFull = false;
345
0
            bool bDoNothing = false;
346
347
            // #i41424# Introduced a couple of
348
            // Push()-Pop() pairs here. The reason for this is that a
349
            // Right()-Left() combination does not make sure, that
350
            // the cursor will be in its initial state, because there
351
            // may be a numbering in front of the next paragraph.
352
0
            SwCursorShell::Push();
353
354
0
            if (SwCursorShell::Right(1, SwCursorSkipMode::Chars))
355
0
            {
356
0
                const SwTableNode* pCurrTableNd = IsCursorInTable();
357
0
                bDelFull = bCheckDelFull && pCurrTableNd && pCurrTableNd != pWasInTableNd;
358
0
                if (!bDelFull && (IsCursorInTable() || (pCurrTableNd != pWasInTableNd)))
359
0
                {
360
                    // #108049# Save the startnode of the current cell.
361
                    // May be different to pSNdOld as we have moved.
362
0
                    const SwStartNode* pSNdNew = pCurrTableNd ?
363
0
                        GetCursor()->GetPointNode().FindTableBoxStartNode() : nullptr;
364
365
                    // tdf#115132 Only keep cursor position instead of deleting
366
                    // if we have moved to a different cell
367
0
                    bDoNothing = pSNdOld != pSNdNew;
368
0
                }
369
0
            }
370
371
            // restore cursor
372
0
            SwTextNode* pNewTextNode = GetCursor()->GetPointNode().GetTextNode();
373
0
            SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
374
375
0
            if (bDelFull)
376
0
            {
377
0
                DelFullPara();
378
0
                UpdateAttr();
379
0
            }
380
381
0
            if (pOldTextNode && pNewTextNode && pNewTextNode != pOldTextNode)
382
0
            {
383
0
                SwRootFrame* pLayout = mxDoc->getIDocumentLayoutAccess().GetCurrentLayout();
384
0
                if (pLayout)
385
0
                {
386
0
                    auto pOldFrame = static_cast<SwTextFrame*>(pOldTextNode->getLayoutFrame(pLayout));
387
0
                    auto pNewFrame = static_cast<SwTextFrame*>(pNewTextNode->getLayoutFrame(pLayout));
388
0
                    if (pOldFrame && pNewFrame && pOldFrame->HasSplitFlyDrawObjs() && pNewFrame->HasSplitFlyDrawObjs())
389
0
                    {
390
                        // We have a selection where both the old and the new position is an anchor
391
                        // for a potentially split fly. Don't allow join of the nodes in this case,
392
                        // since the layout supports multiple anchors for one split fly, but it
393
                        // doesn't support the usage of the same anchor for multiple split flys.
394
0
                        bDoNothing = true;
395
0
                    }
396
0
                }
397
0
            }
398
399
0
            if (bDelFull || bDoNothing)
400
0
                break;
401
0
        }
402
403
0
        {
404
            // If we are just ahead of a fieldmark, then remove it completely
405
0
            sw::mark::Fieldmark *const pFm = getIDocumentMarkAccess()->getFieldmarkAt(*GetCursor()->GetPoint());
406
0
            if (pFm && pFm->GetMarkStart() == *GetCursor()->GetPoint())
407
0
            {
408
0
                mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
409
0
                IDocumentMarkAccess::DeleteFieldmarkCommand(*pFm);
410
0
                getIDocumentMarkAccess()->deleteMark(pFm);
411
0
                mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
412
0
                bRet = true;
413
0
                break;
414
0
            }
415
0
        }
416
417
0
        OpenMark();
418
0
        SwCursorShell::Right(1, SwCursorSkipMode::Cells);
419
0
        bRet = Delete(true);
420
0
        CloseMark( bRet );
421
0
        break;
422
423
0
    case SelectionType::Frame:
424
0
    case SelectionType::Graphic:
425
0
    case SelectionType::Ole:
426
0
    case SelectionType::DrawObject:
427
0
    case SelectionType::DrawObjectEditMode:
428
0
    case SelectionType::DbForm:
429
0
        {
430
            // Group deletion of the object and its comment together
431
            // (also as-character anchor conversion at track changes)
432
0
            mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
433
434
            // #108205# Remember object's position.
435
0
            Point aTmpPt = GetObjRect().TopLeft();
436
437
            // Remember the anchor of the selected object before deletion.
438
0
            std::optional<SwPosition> oAnchor;
439
0
            RndStdIds eAnchorId = RndStdIds::FLY_AT_PARA;
440
0
            SwFlyFrame* pFly = GetSelectedFlyFrame();
441
0
            SwFrameFormat* pFormat = nullptr;
442
0
            if (pFly)
443
0
            {
444
0
                pFormat = pFly->GetFormat();
445
0
                if (pFormat)
446
0
                {
447
0
                    eAnchorId = pFormat->GetAnchor().GetAnchorId();
448
                    // to-character anchor conversion at track changes
449
0
                    if ( IsRedlineOn() && (eAnchorId != RndStdIds::FLY_AS_CHAR &&
450
0
                                           eAnchorId != RndStdIds::FLY_AT_CHAR) )
451
0
                    {
452
0
                        SfxItemSetFixed<RES_ANCHOR, RES_ANCHOR> aSet(GetAttrPool());
453
0
                        GetFlyFrameAttr(aSet);
454
0
                        SwFormatAnchor aAnch(RndStdIds::FLY_AT_CHAR);
455
0
                        aSet.Put(aAnch);
456
0
                        SetFlyFrameAttr(aSet);
457
0
                        eAnchorId = pFormat->GetAnchor().GetAnchorId();
458
0
                    }
459
0
                    if ((eAnchorId == RndStdIds::FLY_AS_CHAR || eAnchorId == RndStdIds::FLY_AT_CHAR)
460
0
                        && pFormat->GetAnchor().GetAnchorNode())
461
0
                    {
462
0
                        oAnchor.emplace(*pFormat->GetAnchor().GetContentAnchor());
463
                        // set cursor before the anchor point
464
0
                        if ( IsRedlineOn() )
465
0
                            *GetCurrentShellCursor().GetPoint() = *oAnchor;
466
0
                    }
467
0
                }
468
0
            }
469
470
            // track changes: create redline at anchor point of the image to record the deletion
471
0
            if ( IsRedlineOn() && oAnchor && SelectionType::Graphic & nSelection && pFormat &&
472
0
                    ( eAnchorId == RndStdIds::FLY_AT_CHAR || eAnchorId == RndStdIds::FLY_AS_CHAR ) )
473
0
            {
474
0
                sal_Int32 nRedlineLength = 1;
475
                // create a double CH_TXT_TRACKED_DUMMY_CHAR anchor point of the image to record the
476
                // deletion, if needed (otherwise use the existing anchor point of the image anchored
477
                // *as* character)
478
0
                if ( eAnchorId == RndStdIds::FLY_AT_CHAR )
479
0
                {
480
0
                    nRedlineLength = 2;
481
0
                    LeaveSelFrameMode();
482
0
                    UnSelectFrame();
483
0
                    RedlineFlags eOld = GetRedlineFlags();
484
0
                    SetRedlineFlags( eOld | RedlineFlags::Ignore );
485
0
                    Insert( OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) +
486
0
                            OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
487
0
                    SwFormatAnchor anchor(RndStdIds::FLY_AT_CHAR);
488
0
                    SwCursorShell::Left(1, SwCursorSkipMode::Chars);
489
0
                    anchor.SetAnchor(GetCursor()->GetPoint());
490
0
                    GetDoc()->SetAttr(anchor, *pFormat);
491
0
                    SetRedlineFlags( eOld );
492
0
                    SwCursorShell::Left(1, SwCursorSkipMode::Chars);
493
0
                }
494
0
                OpenMark();
495
0
                SwCursorShell::Right(nRedlineLength, SwCursorSkipMode::Chars);
496
0
                bRet = Delete(false);
497
0
                CloseMark( bRet );
498
0
            }
499
0
            else
500
0
                DelSelectedObj();
501
502
0
            if (oAnchor)
503
0
            {
504
0
                SwTextNode* pTextNode = oAnchor->GetNode().GetTextNode();
505
0
                if (pTextNode)
506
0
                {
507
0
                    const SwTextField* pField(
508
0
                        pTextNode->GetFieldTextAttrAt(oAnchor->GetContentIndex(), ::sw::GetTextAttrMode::Default));
509
0
                    if (pField
510
0
                        && dynamic_cast<const SwPostItField*>(pField->GetFormatField().GetField()))
511
0
                    {
512
                        // Remove the comment of the deleted object.
513
0
                        *GetCurrentShellCursor().GetPoint() = *oAnchor;
514
0
                        DelRight();
515
0
                    }
516
0
                }
517
0
            }
518
519
0
            mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
520
521
            // #108205# Set cursor to remembered position.
522
0
            SetCursor(&aTmpPt);
523
524
0
            LeaveSelFrameMode();
525
0
            UnSelectFrame();
526
0
            OSL_ENSURE( !IsFrameSelected(),
527
0
                    "<SwWrtShell::DelRight(..)> - <SwWrtShell::UnSelectFrame()> should unmark all objects" );
528
            // leave draw mode, if necessary.
529
0
            {
530
0
                if (GetView().GetDrawFuncPtr())
531
0
                {
532
0
                    GetView().GetDrawFuncPtr()->Deactivate();
533
0
                    GetView().SetDrawFuncPtr(nullptr);
534
0
                }
535
0
                if ( GetView().IsDrawMode() )
536
0
                {
537
0
                    GetView().LeaveDrawCreate();
538
0
                }
539
0
            }
540
0
        }
541
542
        // <IsFrameSelected()> can't be true - see above.
543
0
        {
544
0
            nSelection = GetSelectionType();
545
0
            if ( SelectionType::Frame & nSelection ||
546
0
                 SelectionType::Graphic & nSelection ||
547
0
                 SelectionType::Ole & nSelection ||
548
0
                 SelectionType::DrawObject & nSelection )
549
0
            {
550
0
                EnterSelFrameMode();
551
0
                GotoNextFly();
552
0
            }
553
0
        }
554
0
        bRet = true;
555
0
        break;
556
0
    default: break;
557
0
    }
558
0
    return bRet;
559
0
}
560
561
void SwWrtShell::DelToEndOfPara()
562
0
{
563
0
    SwActContext aActContext(this);
564
0
    ResetCursorStack();
565
0
    Push();
566
0
    SetMark();
567
0
    if( !MovePara(GoCurrPara,fnParaEnd))
568
0
    {
569
0
        Pop(SwCursorShell::PopMode::DeleteCurrent);
570
0
        return;
571
0
    }
572
0
    bool bRet = Delete(false);
573
0
    Pop(SwCursorShell::PopMode::DeleteCurrent);
574
0
    if( bRet )
575
0
        UpdateAttr();
576
0
}
577
578
void SwWrtShell::DelToStartOfPara()
579
0
{
580
0
    SwActContext aActContext(this);
581
0
    ResetCursorStack();
582
0
    Push();
583
0
    SetMark();
584
0
    if( !MovePara(GoCurrPara,fnParaStart))
585
0
    {
586
0
        Pop(SwCursorShell::PopMode::DeleteCurrent);
587
0
        return;
588
0
    }
589
0
    bool bRet = Delete(false);
590
0
    Pop(SwCursorShell::PopMode::DeleteCurrent);
591
0
    if( bRet )
592
0
        UpdateAttr();
593
0
}
594
595
// All erase operations should work with Find instead with
596
// Nxt-/PrvDelim, because the latter works with Wrap Around
597
// -- that's probably not wished.
598
599
void SwWrtShell::DelToStartOfSentence()
600
0
{
601
0
    if(IsStartOfDoc())
602
0
        return;
603
0
    OpenMark();
604
0
    bool bRet = BwdSentence_() && Delete(false);
605
0
    CloseMark( bRet );
606
0
}
607
608
bool SwWrtShell::DelToEndOfSentence()
609
0
{
610
0
    if(IsEndOfDoc())
611
0
        return false;
612
0
    OpenMark();
613
0
    bool bRet(false);
614
    // fdo#60967: special case that is documented in help: delete
615
    // paragraph following table if cursor is at end of last cell in table
616
0
    if (IsEndOfTable())
617
0
    {
618
0
        Push();
619
0
        ClearMark();
620
0
        if (SwCursorShell::Right(1,SwCursorSkipMode::Chars))
621
0
        {
622
0
            SetMark();
623
0
            if (!IsEndPara()) // can only be at the end if it's empty
624
0
            {   // for an empty paragraph this would actually select the _next_
625
0
                SwCursorShell::MovePara(GoCurrPara, fnParaEnd);
626
0
            }
627
0
            if (!IsEndOfDoc()) // do not delete last paragraph in body text
628
0
            {
629
0
                bRet = DelFullPara();
630
0
            }
631
0
        }
632
0
        Pop(SwCursorShell::PopMode::DeleteCurrent);
633
0
    }
634
0
    else
635
0
    {
636
0
        bRet = FwdSentence_() && Delete(false);
637
0
    }
638
0
    CloseMark( bRet );
639
0
    return bRet;
640
0
}
641
642
void SwWrtShell::DelNxtWord()
643
0
{
644
0
    if(IsEndOfDoc())
645
0
        return;
646
0
    SwActContext aActContext(this);
647
0
    ResetCursorStack();
648
0
    EnterStdMode();
649
0
    SetMark();
650
0
    if(IsEndWrd() && !IsStartWord())
651
0
        NxtWrdForDelete(); // #i92468#
652
0
    if(IsStartWord() || IsEndPara())
653
0
        NxtWrdForDelete(); // #i92468#
654
0
    else
655
0
        EndWrd();
656
657
0
    bool bRet = Delete(false);
658
0
    if( bRet )
659
0
        UpdateAttr();
660
0
    else
661
0
        SwapPam();
662
0
    ClearMark();
663
0
}
664
665
void SwWrtShell::DelPrvWord()
666
0
{
667
0
    if(IsStartOfDoc())
668
0
        return;
669
0
    SwActContext aActContext(this);
670
0
    ResetCursorStack();
671
0
    EnterStdMode();
672
0
    SetMark();
673
0
    if ( !IsStartWord() ||
674
0
         !PrvWrdForDelete() ) // #i92468#
675
0
    {
676
0
        if (IsEndWrd() || IsSttPara())
677
0
            PrvWrdForDelete(); // #i92468#
678
0
        else
679
0
            SttWrd();
680
0
    }
681
0
    bool bRet = Delete(false);
682
0
    if( bRet )
683
0
        UpdateAttr();
684
0
    else
685
0
        SwapPam();
686
0
    ClearMark();
687
0
}
688
689
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */