tdf#133957 sw: SelectAll should select fly in empty section

Ctrl+A should select everything in the section; if the section is empty,
there's no text to select, and then the shell will cancel the selection
because SwCursorShell::HasSelection() returns false - so check if
there are flys anchored there, which fixes the Copy.

To fix Delete, a few more checks for empty selection need to be changed.

Change-Id: If54160bdca976ad5f153b89cf8492f4da1e774b7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96324
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@cib.de>
(cherry picked from commit 2d89b9929e85bede4c72684a12e7508751875f0e)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96368
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx
index d449de1f..c76a1df 100644
--- a/sw/inc/undobj.hxx
+++ b/sw/inc/undobj.hxx
@@ -152,6 +152,9 @@
bool IsSelectFrameAnchoredAtPara(SwPosition const & rAnchorPos,
        SwPosition const & rStart, SwPosition const & rEnd,
        DelContentType const nDelContentType = DelContentType::AllMask);
/// check at-char and at-para flys in rDoc
bool IsFlySelectedByCursor(SwDoc const & rDoc,
        SwPosition const & rStart, SwPosition const & rEnd);

// This class has to be inherited into an Undo-object if it saves content
// for Redo/Undo...
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index f373453..7e0defb 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -71,6 +71,7 @@
#include <vcl/uitest/eventdescription.hxx>
#include <tabcol.hxx>
#include <wrtsh.hxx>
#include <undobj.hxx>
#include <boost/property_tree/json_parser.hpp>

using namespace com::sun::star;
@@ -2486,7 +2487,10 @@
bool SwCursorShell::HasSelection() const
{
    const SwPaM* pCursor = getShellCursor( true );
    return IsTableMode() || ( pCursor->HasMark() && *pCursor->GetPoint() != *pCursor->GetMark() );
    return IsTableMode()
        || (pCursor->HasMark() &&
                (*pCursor->GetPoint() != *pCursor->GetMark()
                || IsFlySelectedByCursor(*GetDoc(), *pCursor->Start(), *pCursor->End())));
}

void SwCursorShell::CallChgLnk()
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 403089b..456b1ba 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4059,8 +4059,11 @@
{
    SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();

    if( !rPam.HasMark() || *pStt >= *pEnd )
    if (!rPam.HasMark()
        || (*pStt == *pEnd && !IsFlySelectedByCursor(m_rDoc, *pStt, *pEnd)))
    {
        return false;
    }

    if( m_rDoc.GetAutoCorrExceptWord() )
    {
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 162be4b..2951b56 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -31,6 +31,7 @@
#include <edimp.hxx>
#include <IMark.hxx>
#include <docary.hxx>
#include <undobj.hxx>
#include <SwRewriter.hxx>
#include <globals.hrc>

@@ -41,8 +42,12 @@
{
    bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
    // only for selections
    if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
    if (!rPam.HasMark()
        || (*rPam.GetPoint() == *rPam.GetMark()
            && !IsFlySelectedByCursor(*GetDoc(), *rPam.Start(), *rPam.End())))
    {
        return;
    }

    // Is the selection in a table? Then delete only the content of the selected boxes.
    // Here, there are two cases:
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index b126965..30298fe 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -565,28 +565,9 @@
    // tdf#132725 - if at-char/at-para flys would be deleted, don't group!
    // DelContentIndex() would be called at the wrong time here, the indexes
    // in the stored SwHistoryTextFlyCnt would be wrong when Undo is invoked
    for (SwFrameFormat const*const pFly : *pDoc->GetSpzFrameFormats())
    if (IsFlySelectedByCursor(*pDoc, *pStt, *pEnd))
    {
        SwFormatAnchor const& rAnchor(pFly->GetAnchor());
        switch (rAnchor.GetAnchorId())
        {
            case RndStdIds::FLY_AT_CHAR:
            case RndStdIds::FLY_AT_PARA:
            {
                SwPosition const*const pAnchorPos(rAnchor.GetContentAnchor());
                // can this really be null?
                if (pAnchorPos != nullptr
                    && ((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
                        ? IsDestroyFrameAnchoredAtChar(*pAnchorPos, *pStt, *pEnd)
                        : IsSelectFrameAnchoredAtPara(*pAnchorPos, *pStt, *pEnd)))
                {
                    return false;
                }
            }
            break;
            default: // other types not relevant
            break;
        }
        return false;
    }

    {
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 3e4ddb2..4974f25 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1638,4 +1638,33 @@
                    || (IsAtEndOfSection(rAnchorPos) && IsAtStartOfSection2(rStart)))));
}

bool IsFlySelectedByCursor(SwDoc const & rDoc,
        SwPosition const & rStart, SwPosition const & rEnd)
{
    for (SwFrameFormat const*const pFly : *rDoc.GetSpzFrameFormats())
    {
        SwFormatAnchor const& rAnchor(pFly->GetAnchor());
        switch (rAnchor.GetAnchorId())
        {
            case RndStdIds::FLY_AT_CHAR:
            case RndStdIds::FLY_AT_PARA:
            {
                SwPosition const*const pAnchorPos(rAnchor.GetContentAnchor());
                // can this really be null?
                if (pAnchorPos != nullptr
                    && ((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
                        ? IsDestroyFrameAnchoredAtChar(*pAnchorPos, rStart, rEnd)
                        : IsSelectFrameAnchoredAtPara(*pAnchorPos, rStart, rEnd)))
                {
                    return true;
                }
            }
            break;
            default: // other types not relevant
            break;
        }
    }
    return false;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */