tdf#80715: fix infinite loop in find-and-replace if SwTxtNode full

In a regex searching for "$" to remove the paragraph break, sw_JoinText()
may fail to join the nodes because the maximum size is reached; in this
case the cursor has to be moved to the next node, otherwise the search
will be stuck on that node forever.

This would fix the problem in LO 4.2 but it's actually rather harder to
trigger in 4.3+ because the 16-bit size limit of SwTxtNodes is gone.

(regression from b60ce8465c8f01242354abccebe00742d164af60)

Change-Id: Ie047cad37835adf95afe0d12b94a16ff4aecb17a
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
index e73e4a8..6486526 100644
--- a/sw/source/core/crsr/findtxt.cxx
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -583,9 +583,11 @@ int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,

        boost::scoped_ptr<OUString> pRepl( (bRegExp)
                ? ReplaceBackReferences( rSearchOpt, pCrsr ) : 0 );
        rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange( *pCrsr,
            (pRepl.get()) ? *pRepl : rSearchOpt.replaceString,
            bRegExp );
        bool const bReplaced =
            rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange(
                *pCrsr,
                (pRepl.get()) ? *pRepl : rSearchOpt.replaceString,
                bRegExp );
        rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );

        if( bRegExp )
@@ -599,7 +601,15 @@ int SwFindParaText::Find( SwPaM* pCrsr, SwMoveFn fnMove,
                p->MoveTo( const_cast<SwPaM*>(pRegion) );
            } while( p != pPrev );
        }
        pCrsr->Start()->nContent = nSttCnt;
        if (bRegExp && !bReplaced)
        {   // fdo#80715 avoid infinite loop if join failed
            bool bRet = ((fnMoveForward == fnMove) ? &GoNextPara : &GoPrevPara)
                (*pCrsr, fnMove);
            (void) bRet;
            assert(bRet); // if join failed, next node must be SwTxtNode
        }
        else
            pCrsr->Start()->nContent = nSttCnt;
        return FIND_NO_RING;
    }
    return bFnd ? FIND_FOUND : FIND_NOT_FOUND;
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 12c3345..4323e00 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3982,11 +3982,14 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
        }
    }

    if( bJoinTxt )
        ::sw_JoinText( rPam, bJoinPrev );
    bool bRet(true);
    if (bJoinTxt)
    {
        bRet = ::sw_JoinText(rPam, bJoinPrev);
    }

    m_rDoc.getIDocumentState().SetModified();
    return true;
    return bRet;
}

SwFlyFrmFmt* DocumentContentOperationsManager::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 5f00cc5..01c0b16 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -323,7 +323,7 @@ void sw_GetJoinFlags( SwPaM& rPam, bool& rJoinTxt, bool& rJoinPrev )
    }
}

void sw_JoinText( SwPaM& rPam, bool bJoinPrev )
bool sw_JoinText( SwPaM& rPam, bool bJoinPrev )
{
    SwNodeIndex aIdx( rPam.GetPoint()->nNode );
    SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
@@ -445,7 +445,9 @@ void sw_JoinText( SwPaM& rPam, bool bJoinPrev )
            }
            pTxtNd->JoinNext();
        }
        return true;
    }
    else return false;
}

static void lcl_syncGrammarError( SwTxtNode &rTxtNode, linguistic2::ProofreadingResult& rResult,
diff --git a/sw/source/core/inc/docedt.hxx b/sw/source/core/inc/docedt.hxx
index 0d7513e..53ebea1 100644
--- a/sw/source/core/inc/docedt.hxx
+++ b/sw/source/core/inc/docedt.hxx
@@ -20,7 +20,7 @@
#ifndef INCLUDED_SW_SOURCE_CORE_INC_DOCEDT_HXX
#define INCLUDED_SW_SOURCE_CORE_INC_DOCEDT_HXX

void sw_JoinText( SwPaM& rPam, bool bJoinPrev );
bool sw_JoinText( SwPaM& rPam, bool bJoinPrev );

void sw_GetJoinFlags( SwPaM& rPam, bool& rJoinTxt, bool& rJoinPrev );