editeng/source/editeng/editview.cxx |    7 +-
 include/editeng/editview.hxx        |    2 
 sc/source/ui/inc/gridwin.hxx        |    2 
 sc/source/ui/view/gridwin.cxx       |   89 ++++++++++--------------------------
 4 files changed, 31 insertions(+), 69 deletions(-)

New commits:
commit 8238b887ccecb425f17166d2380afb208bbfdfbb
Author:     Justin Luth <[email protected]>
AuthorDate: Mon Feb 21 10:17:36 2022 +0200
Commit:     Eike Rathke <[email protected]>
CommitDate: Fri Feb 25 15:22:46 2022 +0100

    tdf#81894 sc spelling: choose correct cell when in edit mode
    
    In edit mode, text that is too large to fit inside the cell
    will expand to cover other columns (or rows if cell wraps).
    GetPosFromPixel doesn't account for this, so it needs to
    be done separately. (SHOULD the function itself take this
    into account? Probably, but it is used a LOT,
    so I'm afraid to mess with it.)
    
    This patch fixes two situations in bug 81894 comment 25's example.
    1.) Open Francewhoa---2017-May-29---speadsheet.ods
    2.) Double click on A1 to enter edit mode.
    Notice that the cell expands to cover A1:A3.
    3.) Right click on "productivityy".
    
    Before the patch, the spell check was inspecting empty cell A2,
    and thus showed the edit popup.
    With the patch, the spell check is using cell A1,
    and thus provides spelling suggestions, as expected.
    [This patch depends on this bug report's prior comit.]
    
    4.) Look at B3 and notice misspelled words spilling over from A3.
    Double click on B3 to enter edit mode.
    5.) Right click on the position where the misspelled word had been.
    
    Before the patch, a spelling suggestion was provided,
    even though we right-clicked on an empty place in a different col.
    After the patch, we get the normal edit popup.
    
    Change-Id: I58fbf60711a5c010263b525a96383a805be1b3ca
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130298
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <[email protected]>

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 5a8c9625c332..0f01233d64a9 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -3182,9 +3182,24 @@ void ScGridWindow::Command( const CommandEvent& rCEvt )
     Point aPosPixel = rCEvt.GetMousePosPixel();
     Point aMenuPos = aPosPixel;
 
+    bool bPosIsInEditView = mrViewData.HasEditView(eWhich);
     SCCOL nCellX = -1;
     SCROW nCellY = -1;
     mrViewData.GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, 
nCellY);
+    // GetPosFromPixel ignores the fact that when editing a cell, the cell 
might grow to cover
+    // other rows/columns. In addition, the mouse might now be outside the 
edited cell.
+    if (bPosIsInEditView)
+    {
+        if (nCellX >= mrViewData.GetEditViewCol() && nCellX <= 
mrViewData.GetEditEndCol())
+            nCellX = mrViewData.GetEditViewCol();
+        else
+            bPosIsInEditView = false;
+
+        if (nCellY >= mrViewData.GetEditViewRow() && nCellY <= 
mrViewData.GetEditEndRow())
+            nCellY = mrViewData.GetEditViewRow();
+        else
+            bPosIsInEditView = false;
+    }
 
     bool bSpellError = false;
     SCCOL nColSpellError = nCellX;
@@ -3216,7 +3231,7 @@ void ScGridWindow::Command( const CommandEvent& rCEvt )
             // Find the first string to the left for spell checking in case 
the current cell is empty.
             ScAddress aPos(nCellX, nCellY, nTab);
             ScRefCellValue aSpellCheckCell(rDoc, aPos);
-            while (aSpellCheckCell.meType == CELLTYPE_NONE)
+            while (!bPosIsInEditView && aSpellCheckCell.meType == 
CELLTYPE_NONE)
             {
                 // Loop until we get the first non-empty cell in the row.
                 aPos.IncCol(-1);
commit cf18038c66075f7a18d89e47f3a2ab1a5bf7c4fd
Author:     Justin Luth <[email protected]>
AuthorDate: Sat Feb 19 20:22:23 2022 +0200
Commit:     Eike Rathke <[email protected]>
CommitDate: Fri Feb 25 15:22:32 2022 +0100

    tdf#81894 sc spelling: eliminate separate(inaccurate) check
    
    ExecuteSpellPopup is quite accurate at identifying whether
    the spelling at PosPixel is a spelling error or not.
    If it is not a misspelled word, then it just silently returns.
    
    If we make this a bDone flag, then it will just move
    on to the normal right-click dialog.
    
    There are a few additional scenarios that need to be
    handled (mainly in terms of showing the edit-mode menu
    instead of the full format menu, and also not
    always returning the correct row/col when in edit mode).
    I will do them in separate patches so that
    each edge case can be clearly seen and handled.
    They all rely on this patch being applied first.
    
    This is the base patch. Too many things simply don't
    work with the interim check, so I removed it.
    (Part of the problem is that EditView kicks on and off,
    and then a new CompleteOnlineSpelling needs to be run before
    IsWrongSpelledWordAtPos can return a meaningful answer.)
    
    This patch specifically fixes the problem of not
    opening SpellPopup on a misspelled word in a wrapped-cell.
    Steps to reproduce:
    1.) Open LOv4304.ods from bug 81894 comment 6.
    2.) Right-click on "spellng" in cell B12.
    
    Before the patch, a full format popup was displayed
    (not in edit mode) because IsSpellErrorAtPos returned
    false, when it should have been true.
    
    With this patch, spelling suggestions are provided.
    
    As an example of an edge case, also notice:
    3.) double-click on cell B4 (to enter edit mode)
    4.) right click on "spellng" which appears to be in D4
    
    Before the patch, nothing happened at all,
    but with the patch at least the fall-back menu is displayed.
    (EditView never switches out of cell B,
    so SpellPopup is looking at wrong information.)
    
    Change-Id: I91d413debc58de832dc7413034618e9e2bae3dd5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130297
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <[email protected]>
    Reviewed-by: Eike Rathke <[email protected]>

diff --git a/editeng/source/editeng/editview.cxx 
b/editeng/source/editeng/editview.cxx
index a422cb55c85e..17ecb94b9dd1 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -978,7 +978,7 @@ static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, 
LanguageType nGuessLa
     pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, 
aStream.str().c_str());
 }
 
-void EditView::ExecuteSpellPopup(const Point& rPosPixel, const 
Link<SpellCallbackInfo&,void> &rCallBack)
+bool EditView::ExecuteSpellPopup(const Point& rPosPixel, const 
Link<SpellCallbackInfo&,void> &rCallBack)
 {
     OutputDevice& rDevice = pImpEditView->GetOutputDevice();
     Point aPos(rDevice.PixelToLogic(rPosPixel));
@@ -987,7 +987,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, 
const Link<SpellCallbac
     Reference< linguistic2::XSpellChecker1 >  xSpeller( 
pImpEditView->pEditEngine->pImpEditEngine->GetSpeller() );
     ESelection aOldSel = GetSelection();
     if ( !(xSpeller.is() && pImpEditView->IsWrongSpelledWord( aPaM, true )) )
-        return;
+        return false;
 
     // PaMtoEditCursor returns Logical units
     tools::Rectangle aTempRect = 
pImpEditView->pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, 
GetCursorFlags::TextOnly );
@@ -1167,7 +1167,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, 
const Link<SpellCallbac
         xPopupMenu->remove("autocorrectdlg");
 
         LOKSendSpellPopupMenu(*xPopupMenu, nGuessLangWord, nGuessLangPara, 
nWords);
-        return;
+        return true;
     }
 
     OString sId = xPopupMenu->popup_at_rect(pPopupParent, aTempRect);
@@ -1267,6 +1267,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, 
const Link<SpellCallbac
     {
         SetSelection( aOldSel );
     }
+    return true;
 }
 
 OUString EditView::SpellIgnoreWord()
diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx
index 61b659dfb152..6d3a09664767 100644
--- a/include/editeng/editview.hxx
+++ b/include/editeng/editview.hxx
@@ -305,7 +305,7 @@ public:
 
     bool            IsCursorAtWrongSpelledWord();
     bool            IsWrongSpelledWordAtPos( const Point& rPosPixel, bool 
bMarkIfWrong = false );
-    void            ExecuteSpellPopup(const Point& rPosPixel, const 
Link<SpellCallbackInfo&,void>& rCallBack);
+    bool            ExecuteSpellPopup(const Point& rPosPixel, const 
Link<SpellCallbackInfo&,void>& rCallBack);
     OUString        SpellIgnoreWord();
 
     void                InsertField( const SvxFieldItem& rFld );
diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx
index 12535cd313e0..988bf55d2a17 100644
--- a/sc/source/ui/inc/gridwin.hxx
+++ b/sc/source/ui/inc/gridwin.hxx
@@ -283,8 +283,6 @@ class SAL_DLLPUBLIC_RTTI ScGridWindow : public vcl::Window, 
public DropTargetHel
     bool            GetEditUrl( const Point& rPos,
                                 OUString* pName=nullptr, OUString* 
pUrl=nullptr, OUString* pTarget=nullptr );
 
-    bool IsSpellErrorAtPos( const Point& rPos, SCCOL nCol1, SCROW nRow );
-
     bool            HitRangeFinder( const Point& rMouse, RfCorner& rCorner, 
sal_uInt16* pIndex,
                                     SCCOL* pAddX, SCROW* pAddY );
 
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 1357a543659c..5a8c9625c332 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -3229,12 +3229,9 @@ void ScGridWindow::Command( const CommandEvent& rCEvt )
             if (aPos.Col() >= 0 && (aSpellCheckCell.meType == CELLTYPE_STRING 
|| aSpellCheckCell.meType == CELLTYPE_EDIT))
                 nColSpellError = aPos.Col();
 
+            // Is there a missspelled word somewhere in the cell?
+            // A "yes" does not mean that the word under the mouse pointer is 
wrong though.
             bSpellError = (mpSpellCheckCxt->isMisspelled(nColSpellError, 
nCellY));
-            if (bSpellError)
-            {
-                // Check and see if a misspelled word is under the mouse 
pointer.
-                bSpellError = IsSpellErrorAtPos(aPosPixel, nColSpellError, 
nCellY);
-            }
         }
 
         //  #i18735# First select the item under the mouse pointer.
@@ -3248,7 +3245,7 @@ void ScGridWindow::Command( const CommandEvent& rCEvt )
     if ( !bEdit )
     {
         // Edit cell with spelling errors?
-        // tdf#127341 the formally used GetEditUrl(aPosPixel) additionally
+        // tdf#127341 the formerly used GetEditUrl(aPosPixel) additionally
         // to bSpellError activated EditMode here for right-click on URL
         // which prevents the regular context-menu from appearing. Since this
         // is more expected than the context-menu for editing an URL, I removed
@@ -3300,13 +3297,18 @@ void ScGridWindow::Command( const CommandEvent& rCEvt )
 
             const OUString sOldText = pHdl ? pHdl->GetEditString() : "";
 
+            // Only done/shown if a misspelled word is actually under the 
mouse pointer.
             Link<SpellCallbackInfo&,void> aLink = LINK( this, ScGridWindow, 
PopupSpellingHdl );
-            pEditView->ExecuteSpellPopup(aMenuPos, aLink);
+            bDone = pEditView->ExecuteSpellPopup(aMenuPos, aLink);
 
             if (pHdl && pHdl->GetEditString() != sOldText)
                 pHdl->EnterHandler();
 
-            bDone = true;
+            if (!bDone && nColSpellError != nCellX)
+            {
+                // NOTE: This call can change the selection, and the view 
state (edit mode, etc).
+                SelectForContextMenu(aPosPixel, nCellX, nCellY);
+            }
         }
     }
     else if ( !bMouse )
@@ -5767,60 +5769,6 @@ bool ScGridWindow::GetEditUrl( const Point& rPos,
     return false;
 }
 
-bool ScGridWindow::IsSpellErrorAtPos( const Point& rPos, SCCOL nCol1, SCROW 
nRow )
-{
-    if (!mpSpellCheckCxt)
-        return false;
-
-    SCTAB nTab = mrViewData.GetTabNo();
-    ScDocShell* pDocSh = mrViewData.GetDocShell();
-    ScDocument& rDoc = pDocSh->GetDocument();
-
-    ScAddress aCellPos(nCol1, nRow, nTab);
-    ScRefCellValue aCell(rDoc, aCellPos);
-    if (aCell.meType != CELLTYPE_STRING && aCell.meType != CELLTYPE_EDIT)
-        return false;
-
-    const std::vector<editeng::MisspellRanges>* pRanges = 
mpSpellCheckCxt->getMisspellRanges(nCol1, nRow);
-    if (!pRanges)
-        return false;
-
-    const ScPatternAttr* pPattern = rDoc.GetPattern(nCol1, nRow, nTab);
-
-    tools::Rectangle aEditRect = mrViewData.GetEditArea(eWhich, nCol1, nRow, 
this, pPattern, false);
-    if (rPos.Y() < aEditRect.Top())
-        return false;
-
-    std::shared_ptr<ScFieldEditEngine> pEngine = createEditEngine(pDocSh, 
*pPattern);
-
-    Size aPaperSize(1000000, 1000000);
-    pEngine->SetPaperSize(aPaperSize);
-
-    if (aCell.meType == CELLTYPE_EDIT)
-        pEngine->SetTextCurrentDefaults(*aCell.mpEditText);
-    else
-        pEngine->SetTextCurrentDefaults(aCell.mpString->getString());
-
-    tools::Long nTextWidth = 
static_cast<tools::Long>(pEngine->CalcTextWidth());
-
-    MapMode aEditMode = mrViewData.GetLogicMode(eWhich);
-    tools::Rectangle aLogicEdit = PixelToLogic(aEditRect, aEditMode);
-    Point aLogicClick = PixelToLogic(rPos, aEditMode);
-
-    aLogicEdit.setWidth(nTextWidth + 1);
-
-    if (!aLogicEdit.Contains(aLogicClick))
-        return false;
-
-    pEngine->SetControlWord(pEngine->GetControlWord() | 
EEControlBits::ONLINESPELLING);
-    pEngine->SetAllMisspellRanges(*pRanges);
-
-    EditView aTempView(pEngine.get(), this);
-    aTempView.SetOutputArea(aLogicEdit);
-
-    return aTempView.IsWrongSpelledWordAtPos(rPos);
-}
-
 bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& 
rScenRange )
 {
     ScDocument& rDoc = mrViewData.GetDocument();

Reply via email to