[Libreoffice-commits] core.git: sw/inc sw/source

Michael Stahl mstahl at redhat.com
Wed Sep 9 05:15:12 PDT 2015


 sw/inc/ndtxt.hxx                       |    5 +++
 sw/source/core/doc/doc.cxx             |    4 +--
 sw/source/core/inc/wrong.hxx           |    3 +-
 sw/source/core/layout/layact.cxx       |    3 +-
 sw/source/core/text/txtfrm.cxx         |    2 -
 sw/source/core/text/wrong.cxx          |   20 +++++++++------
 sw/source/core/txtnode/ndtxt.cxx       |   14 +++++-----
 sw/source/core/txtnode/txtedt.cxx      |   43 +++++++++++++++++++++++----------
 sw/source/core/unocore/unoflatpara.cxx |    5 +++
 sw/source/core/unocore/unoobj.cxx      |    2 -
 10 files changed, 66 insertions(+), 35 deletions(-)

New commits:
commit 4c91e94e892943ef5e031d65f6f42864233cb4cd
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Sep 9 10:30:04 2015 +0200

    tdf#92036: sw: fix idle spelling loop
    
    There is a sort of intentional infinite loop in the idle spell checking
    handler: while the user is typing a word, it should not be marked as
    invalid yet, in order not to annoy them with red underlines.
    
    So the word where the cursor is positioned always remained dirty, unless
    you happen to have a grammar checker enabled, which clears the
    paragraph's dirty flag from a separate thread.
    
    To avoid the infinite loop, add another spell checking state "PENDING"
    which is the same as dirty except that it should cancel the idle spell
    checking.
    
    The idle spell checking will run again when the user does the next
    editing operation.  Notably this means if the user just moves the cursor
    out of the wrongly spelled word, it won't be underlined yet, but that
    appears a minor issue, and checking when the cursor leaves the word
    appears too hard to implement.
    
    Change-Id: Ifb3d6d17f94f9f1cfad82e70dfa79f1594c38647

diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 261fbdf..ba56bb5 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -184,13 +184,16 @@ class SW_DLLPUBLIC SwTextNode: public SwContentNode, public ::sfx2::Metadatable
     void DelFrms_TextNodePart();
 
 public:
+    enum class WrongState { TODO, PENDING, DONE };
+
     bool IsWordCountDirty() const;
+    WrongState GetWrongDirty() const;
     bool IsWrongDirty() const;
     bool IsGrammarCheckDirty() const;
     bool IsSmartTagDirty() const;
     bool IsAutoCompleteWordDirty() const;
     void SetWordCountDirty( bool bNew ) const;
-    void SetWrongDirty( bool bNew ) const;
+    void SetWrongDirty(WrongState eNew) const;
     void SetGrammarCheckDirty( bool bNew ) const;
     void SetSmartTagDirty( bool bNew ) const;
     void SetAutoCompleteWordDirty( bool bNew ) const;
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 789fbb9..df4a5f6 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -1097,14 +1097,14 @@ static bool lcl_SpellAndGrammarAgain( const SwNodePtr& rpNd, void* pArgs )
         {
             if( pTextNode->GetWrong() &&
                 pTextNode->GetWrong()->InvalidateWrong() )
-                pTextNode->SetWrongDirty( true );
+                pTextNode->SetWrongDirty(SwTextNode::WrongState::TODO);
             if( pTextNode->GetGrammarCheck() &&
                 pTextNode->GetGrammarCheck()->InvalidateWrong() )
                 pTextNode->SetGrammarCheckDirty( true );
         }
         else
         {
-            pTextNode->SetWrongDirty( true );
+            pTextNode->SetWrongDirty(SwTextNode::WrongState::TODO);
             if( pTextNode->GetWrong() )
                 pTextNode->GetWrong()->SetInvalid( 0, COMPLETE_STRING );
             pTextNode->SetGrammarCheckDirty( true );
diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx
index 085ab615..840ca66 100644
--- a/sw/source/core/inc/wrong.hxx
+++ b/sw/source/core/inc/wrong.hxx
@@ -209,7 +209,8 @@ public:
     inline void Validate(){ nBeginInvalid = nEndInvalid = COMPLETE_STRING; }
     void Invalidate( sal_Int32 nBegin, sal_Int32 nEnd );
     bool InvalidateWrong();
-    bool Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
+    enum class FreshState { FRESH, CURSOR, NOTHING };
+    FreshState Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
             sal_Int32 nLen, sal_uInt16 nIndex, sal_Int32 nCursorPos );
     sal_uInt16 GetWrongPos( sal_Int32 nValue ) const;
 
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index e8a03f3..500f42f 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1916,7 +1916,8 @@ bool SwLayIdle::_DoIdleJob( const SwContentFrm *pCnt, IdleJobType eJob )
             case ONLINE_SPELLING :
             {
                 SwRect aRepaint( const_cast<SwTextFrm*>(static_cast<const SwTextFrm*>(pCnt))->_AutoSpell( pContentNode, nTextPos ) );
-                bPageValid = bPageValid && !pTextNode->IsWrongDirty();
+                // tdf#92036 PENDING should stop idle spell checking
+                bPageValid = bPageValid && (SwTextNode::WrongState::TODO != pTextNode->GetWrongDirty());
                 if( !bPageValid )
                     bAllValid = false;
                 if ( aRepaint.HasArea() )
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index b240c63..c996bdc 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -845,7 +845,7 @@ static void lcl_SetWrong( SwTextFrm& rFrm, sal_Int32 nPos, sal_Int32 nCnt, bool
             pTextNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
             pTextNode->GetSmartTags()->SetInvalid( nPos, nEnd );
         }
-        pTextNode->SetWrongDirty( true );
+        pTextNode->SetWrongDirty(SwTextNode::WrongState::TODO);
         pTextNode->SetGrammarCheckDirty( true );
         pTextNode->SetWordCountDirty( true );
         pTextNode->SetAutoCompleteWordDirty( true );
diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx
index 0ea4c52..1fb87d9 100644
--- a/sw/source/core/text/wrong.cxx
+++ b/sw/source/core/text/wrong.cxx
@@ -356,11 +356,17 @@ void SwWrongList::Move( sal_Int32 nPos, sal_Int32 nDiff )
 
    @return <true> if ???
  */
-bool SwWrongList::Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
-                             sal_Int32 nLen, sal_uInt16 nIndex, sal_Int32 nCursorPos )
+auto SwWrongList::Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
+     sal_Int32 nLen, sal_uInt16 nIndex, sal_Int32 nCursorPos ) -> FreshState
 {
-    // length of word must be greater than 0 and cursor position must be outside the word
-    bool bRet = nLen && ( nCursorPos > nPos + nLen || nCursorPos < nPos );
+    // length of word must be greater than 0
+    // only report a spelling error if the cursor position is outside the word,
+    // so that the user is not annoyed while typing
+    FreshState eRet = (nLen)
+        ? (nCursorPos > nPos + nLen || nCursorPos < nPos)
+            ? FreshState::FRESH
+            : FreshState::CURSOR
+        : FreshState::NOTHING;
 
     sal_Int32 nWrPos = 0;
     sal_Int32 nWrEnd = rEnd;
@@ -383,11 +389,11 @@ bool SwWrongList::Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
     if( nCnt < Count() && nWrPos == nPos && Len( nCnt ) == nLen )
     {
         ++nCnt;
-        bRet = true;
+        eRet = FreshState::FRESH;
     }
     else
     {
-        if( bRet )
+        if (FreshState::FRESH == eRet)
         {
             if( rStart > nPos )
                 rStart = nPos;
@@ -417,7 +423,7 @@ bool SwWrongList::Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
 
     Remove( nIndex, nCnt - nIndex );
 
-    return bRet;
+    return eRet;
 }
 
 void SwWrongList::Invalidate( sal_Int32 nBegin, sal_Int32 nEnd )
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index aa37458..08da02c 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -428,7 +428,7 @@ SwContentNode *SwTextNode::SplitContentNode( const SwPosition &rPos )
         {
             pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
         }
-        SetWrongDirty( true );
+        SetWrongDirty(WrongState::TODO);
 
         if( GetGrammarCheck() )
         {
@@ -531,7 +531,7 @@ SwContentNode *SwTextNode::SplitContentNode( const SwPosition &rPos )
     {
         SwWrongList *pList = GetWrong();
         SetWrong( 0, false );
-        SetWrongDirty( true );
+        SetWrongDirty(WrongState::TODO);
 
         SwGrammarMarkUp *pList3 = GetGrammarCheck();
         SetGrammarCheck( 0, false );
@@ -652,7 +652,7 @@ SwContentNode *SwTextNode::JoinNext()
         if( pList )
         {
             pList->JoinList( pTextNode->GetWrong(), nOldLen );
-            SetWrongDirty( true );
+            SetWrongDirty(WrongState::TODO);
             SetWrong( 0, false );
         }
         else
@@ -661,7 +661,7 @@ SwContentNode *SwTextNode::JoinNext()
             if( pList )
             {
                 pList->Move( 0, nOldLen );
-                SetWrongDirty( true );
+                SetWrongDirty(WrongState::TODO);
                 pTextNode->SetWrong( 0, false );
             }
         }
@@ -743,7 +743,7 @@ SwContentNode *SwTextNode::JoinPrev()
         if( pList )
         {
             pList->JoinList( GetWrong(), Len() );
-            SetWrongDirty( true );
+            SetWrongDirty(WrongState::TODO);
             pTextNode->SetWrong( 0, false );
             SetWrong( NULL );
         }
@@ -753,7 +753,7 @@ SwContentNode *SwTextNode::JoinPrev()
             if( pList )
             {
                 pList->Move( 0, nLen );
-                SetWrongDirty( true );
+                SetWrongDirty(WrongState::TODO);
                 SetWrong( 0, false );
             }
         }
@@ -1387,7 +1387,7 @@ const SwTextInputField* SwTextNode::GetOverlappingInputField( const SwTextAttr&
 void SwTextNode::DelFrms_TextNodePart()
 {
     SetWrong( NULL );
-    SetWrongDirty( true );
+    SetWrongDirty(WrongState::TODO);
 
     SetGrammarCheck( NULL );
     SetGrammarCheckDirty( true );
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 582c60f..98095cf 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -1311,6 +1311,7 @@ SwRect SwTextFrm::_AutoSpell( const SwContentNode* pActNode, sal_Int32 nActPos )
     }
 
     bool bFresh = nBegin < nEnd;
+    bool bPending(false);
 
     if( bFresh )
     {
@@ -1353,13 +1354,19 @@ SwRect SwTextFrm::_AutoSpell( const SwContentNode* pActNode, sal_Int32 nActPos )
                             pNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
                             pNode->GetWrong()->SetInvalid( 0, nEnd );
                         }
-                        if( pNode->GetWrong()->Fresh( nChgStart, nChgEnd,
-                            nBegin, nLen, nInsertPos, nActPos ) )
-                            pNode->GetWrong()->Insert( OUString(), 0, nBegin, nLen, nInsertPos++ );
-                        else
+                        SwWrongList::FreshState const eState(pNode->GetWrong()->Fresh(
+                            nChgStart, nChgEnd, nBegin, nLen, nInsertPos, nActPos));
+                        switch (eState)
                         {
-                            nInvStart = nBegin;
-                            nInvEnd = nBegin + nLen;
+                            case SwWrongList::FreshState::FRESH:
+                                pNode->GetWrong()->Insert(OUString(), 0, nBegin, nLen, nInsertPos++);
+                                break;
+                            case SwWrongList::FreshState::CURSOR:
+                                bPending = true; // fall-through to mark as invalid
+                            case SwWrongList::FreshState::NOTHING:
+                                nInvStart = nBegin;
+                                nInvEnd = nBegin + nLen;
+                                break;
                         }
                     }
                 }
@@ -1402,12 +1409,17 @@ SwRect SwTextFrm::_AutoSpell( const SwContentNode* pActNode, sal_Int32 nActPos )
         }
 
         pNode->GetWrong()->SetInvalid( nInvStart, nInvEnd );
-        pNode->SetWrongDirty( COMPLETE_STRING != pNode->GetWrong()->GetBeginInv() );
+        pNode->SetWrongDirty(
+            (COMPLETE_STRING != pNode->GetWrong()->GetBeginInv())
+                ? ((bPending)
+                    ? SwTextNode::WrongState::PENDING
+                    : SwTextNode::WrongState::TODO)
+                : SwTextNode::WrongState::DONE);
         if( !pNode->GetWrong()->Count() && ! pNode->IsWrongDirty() )
             pNode->SetWrong( NULL );
     }
     else
-        pNode->SetWrongDirty( false );
+        pNode->SetWrongDirty(SwTextNode::WrongState::DONE);
 
     if( bAddAutoCmpl )
         pNode->SetAutoCompleteWordDirty( false );
@@ -2115,7 +2127,7 @@ struct SwParaIdleData_Impl
     sal_uLong nNumberOfChars;
     sal_uLong nNumberOfCharsExcludingSpaces;
     bool bWordCountDirty;
-    bool bWrongDirty;                   // Ist das Wrong-Feld auf invalid?
+    SwTextNode::WrongState eWrongDirty; ///< online spell checking needed/done?
     bool bGrammarCheckDirty;
     bool bSmartTagDirty;
     bool bAutoComplDirty;               // die ACompl-Liste muss angepasst werden
@@ -2129,7 +2141,7 @@ struct SwParaIdleData_Impl
         nNumberOfChars      ( 0 ),
         nNumberOfCharsExcludingSpaces ( 0 ),
         bWordCountDirty     ( true ),
-        bWrongDirty         ( true ),
+        eWrongDirty         ( SwTextNode::WrongState::TODO ),
         bGrammarCheckDirty  ( true ),
         bSmartTagDirty      ( true ),
         bAutoComplDirty     ( true ) {};
@@ -2276,17 +2288,22 @@ bool SwTextNode::IsWordCountDirty() const
     return m_pParaIdleData_Impl && m_pParaIdleData_Impl->bWordCountDirty;
 }
 
-void SwTextNode::SetWrongDirty( bool bNew ) const
+void SwTextNode::SetWrongDirty(WrongState eNew) const
 {
     if ( m_pParaIdleData_Impl )
     {
-        m_pParaIdleData_Impl->bWrongDirty = bNew;
+        m_pParaIdleData_Impl->eWrongDirty = eNew;
     }
 }
 
+auto SwTextNode::GetWrongDirty() const -> WrongState
+{
+    return (m_pParaIdleData_Impl) ? m_pParaIdleData_Impl->eWrongDirty : WrongState::DONE;
+}
+
 bool SwTextNode::IsWrongDirty() const
 {
-    return m_pParaIdleData_Impl && m_pParaIdleData_Impl->bWrongDirty;
+    return m_pParaIdleData_Impl && m_pParaIdleData_Impl->eWrongDirty != WrongState::DONE;
 }
 
 void SwTextNode::SetGrammarCheckDirty( bool bNew ) const
diff --git a/sw/source/core/unocore/unoflatpara.cxx b/sw/source/core/unocore/unoflatpara.cxx
index 4af396a..4628abc 100644
--- a/sw/source/core/unocore/unoflatpara.cxx
+++ b/sw/source/core/unocore/unoflatpara.cxx
@@ -199,7 +199,10 @@ void SAL_CALL SwXFlatParagraph::setChecked( ::sal_Int32 nType, sal_Bool bVal ) t
     if (GetTextNode())
     {
         if ( text::TextMarkupType::SPELLCHECK == nType )
-            GetTextNode()->SetWrongDirty( !bVal );
+        {
+            GetTextNode()->SetWrongDirty(
+                (bVal) ? SwTextNode::WrongState::DONE : SwTextNode::WrongState::TODO);
+        }
         else if ( text::TextMarkupType::SMARTTAG == nType )
             GetTextNode()->SetSmartTagDirty( !bVal );
         else if( text::TextMarkupType::PROOFREADING == nType )
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index 779f84a..c3be1b1 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -2514,7 +2514,7 @@ throw (uno::RuntimeException, std::exception)
 
     if ( text::TextMarkupType::SPELLCHECK == nType )
     {
-        txtNode->SetWrongDirty(true);
+        txtNode->SetWrongDirty(SwTextNode::WrongState::TODO);
         txtNode->SetWrong(0);
     }
     else if( text::TextMarkupType::PROOFREADING == nType )


More information about the Libreoffice-commits mailing list