fdo#50801 fix cross-reference text when Caption order is Numbering first

Change-Id: I7306f99c18d0f9cfb3b0ce147ecc200662d23b3d
diff --git a/sw/inc/expfld.hxx b/sw/inc/expfld.hxx
index c15e0a2..0663ef5 100644
--- a/sw/inc/expfld.hxx
+++ b/sw/inc/expfld.hxx
@@ -123,7 +123,7 @@
    virtual bool        QueryValue( com::sun::star::uno::Any& rVal, sal_uInt16 nWhich ) const;
    virtual bool        PutValue( const com::sun::star::uno::Any& rVal, sal_uInt16 nWhich );

    static sal_uInt16   GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc);
    static sal_uInt16   GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc, unsigned nHint = 0);
    // #i82544#
    void                SetLateInitialization() { bLateInitialization = true;}
};
diff --git a/sw/inc/reffld.hxx b/sw/inc/reffld.hxx
index 5d54b6d..6daf7f6 100644
--- a/sw/inc/reffld.hxx
+++ b/sw/inc/reffld.hxx
@@ -48,19 +48,19 @@
enum REFERENCEMARK
{
    REF_BEGIN,
    REF_PAGE = REF_BEGIN,
    REF_CHAPTER,
    REF_CONTENT,
    REF_UPDOWN,
    REF_PAGE_PGDESC,
    REF_ONLYNUMBER,
    REF_ONLYCAPTION,
    REF_ONLYSEQNO,
    REF_PAGE = REF_BEGIN, // "Page"
    REF_CHAPTER,          // "Chapter"
    REF_CONTENT,          // "Reference"
    REF_UPDOWN,           // "Above/Below"
    REF_PAGE_PGDESC,      // "As Page Style"
    REF_ONLYNUMBER,       // "Category and Number"
    REF_ONLYCAPTION,      // "Caption Text"
    REF_ONLYSEQNO,        // "Numbering"
    // --> #i81002#
    // new reference format types for referencing bookmarks and set references
    REF_NUMBER,
    REF_NUMBER_NO_CONTEXT,
    REF_NUMBER_FULL_CONTEXT,
    REF_NUMBER,              // "Number"
    REF_NUMBER_NO_CONTEXT,   // "Number (no context)"
    REF_NUMBER_FULL_CONTEXT, // "Number (full context)"
    REF_END
};

@@ -72,7 +72,7 @@
    SwDoc* pDoc;
protected:
    // Overlay in order to update all ref-fields.
   virtual void Modify( const SfxPoolItem*, const SfxPoolItem * );
    virtual void Modify( const SfxPoolItem*, const SfxPoolItem* );
public:
    SwGetRefFieldType(SwDoc* pDoc );
    virtual SwFieldType*    Copy() const;
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx
index fee0e9c..29aa927 100644
--- a/sw/source/core/fields/expfld.cxx
+++ b/sw/source/core/fields/expfld.cxx
@@ -895,19 +895,21 @@
/* --------------------------------------------------
    Description: Find the index of the reference text
    following the current field
    nHint: search starting position after the current
    field (or 0 if default)
 --------------------------------------------------*/
xub_StrLen SwGetExpField::GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc)
xub_StrLen SwGetExpField::GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc, unsigned nHint)
{
    //
    const SwTxtFld* pTxtFld = rFmt.GetTxtFld();
    const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
    //
    xub_StrLen nRet = *pTxtFld->GetStart() + 1;
    xub_StrLen nRet = nHint ? nHint : *pTxtFld->GetStart() + 1;
    String sNodeText = rTxtNode.GetTxt();
    sNodeText.Erase(0, nRet);
    if(sNodeText.Len())
    {
        //now check if sNodeText starts with a non-alphanumeric character plus a blank
        // now check if sNodeText starts with a non-alphanumeric character plus blanks
        sal_uInt16 nSrcpt = pBreakIt->GetRealScriptOfText( sNodeText, 0 );

        static sal_uInt16 nIds[] =
@@ -934,11 +936,14 @@
            if( !bIsAlphaNum ||
                (c0 == ' ' || c0 == '\t'))
            {
                // ignoring blanks
                nRet++;
                if( sNodeText.Len() > 1 &&
                    (sNodeText.GetChar(1) == ' ' ||
                     sNodeText.GetChar(1) == '\t'))
                    nRet++;
                unsigned i = 1;
                while (i < sNodeText.Len() &&
                    (sNodeText.GetChar(i) == ' ' ||
                     sNodeText.GetChar(i) == '\t')
                )
                    nRet++, i++;
            }
        }
    }
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
index c9f3bf14..420a445 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -67,6 +67,7 @@

#include <set>
#include <map>
#include <algorithm> // min, max

#include <sfx2/childwin.hxx>

@@ -290,16 +291,28 @@
    sTxt.Erase();

    SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
    sal_uInt16 nStt = USHRT_MAX;
    sal_uInt16 nEnd = USHRT_MAX;
    SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( pDoc, sSetRefName,
                                        nSubType, nSeqNo, &nStt, &nEnd );
    // finding the reference target (the number)
    sal_uInt16 nNumStart, nNumEnd;
    SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor(
        pDoc, sSetRefName, nSubType, nSeqNo, &nNumStart, &nNumEnd
    );
    // not found?
    if ( !pTxtNd )
    {
        sTxt = ViewShell::GetShellRes()->aGetRefFld_RefItemNotFound;
        return ;
    }
    // where is the category name (e.g. "Illustration")?
    rtl::OUString const Text = pTxtNd->GetTxt();
    unsigned const nCatStart = Text.indexOf(sSetRefName);
    unsigned const nCatEnd = nCatStart == unsigned(-1) ?
        unsigned(-1) : nCatStart + sSetRefName.getLength();
    bool const bHasCat = nCatStart != unsigned(-1);

    // length of the referenced text
    unsigned const nLen = Text.getLength();

    // which format?
    switch( GetFormat() )
    {
    case REF_CONTENT:
@@ -307,73 +320,95 @@
    case REF_ONLYCAPTION:
    case REF_ONLYSEQNO:
        {
            // needed part of Text
            unsigned nStart, nEnd;

            switch( nSubType )
            {
            case REF_SEQUENCEFLD:
                nEnd = pTxtNd->GetTxt().Len();

                switch( GetFormat() )
                {
                // "Category and Number"
                case REF_ONLYNUMBER:
                    if( nStt + 1 < nEnd )
                        nEnd = nStt + 1;
                    nStt = 0;
                    break;

                case REF_ONLYCAPTION:
                    {
                        const SwTxtAttr* const pTxtAttr =
                            pTxtNd->GetTxtAttrForCharAt(nStt, RES_TXTATR_FIELD);
                        if( pTxtAttr )
                            nStt = SwGetExpField::GetReferenceTextPos(
                                                pTxtAttr->GetFld(), *pDoc );
                        else if( nStt + 1 < nEnd )
                            ++nStt;
                    if (bHasCat) {
                        nStart = std::min<unsigned>(nNumStart, nCatStart);
                        nEnd = std::max<unsigned>(nNumEnd, nCatEnd);
                    } else {
                        nStart = nNumStart;
                        nEnd = nNumEnd;
                    }
                    break;

                // "Caption Text"
                case REF_ONLYCAPTION: {
                    // next alphanumeric character after category+number
                    if (const SwTxtAttr* const pTxtAttr =
                        pTxtNd->GetTxtAttrForCharAt(nNumStart, RES_TXTATR_FIELD)
                    ) {
                        // start searching from nFrom
                        unsigned const nFrom = bHasCat ?
                            std::max<unsigned>(nNumStart + 1, nCatEnd) : nNumStart + 1;
                        nStart = SwGetExpField::GetReferenceTextPos(
                            pTxtAttr->GetFld(), *pDoc, nFrom
                        );
                    } else {
                        nStart = bHasCat ?
                            std::max<unsigned>(nNumEnd, nCatEnd) : nNumEnd;
                    }
                    nEnd = nLen;
                    break;
                }

                // "Numbering"
                case REF_ONLYSEQNO:
                    if( nStt + 1 < nEnd )
                        nEnd = nStt + 1;
                    nStart = nNumStart;
                    nEnd = std::min<unsigned>(nStart + 1, nLen);
                    break;

                // "Reference" (whole Text)
                default:
                    nStt = 0;
                    nStart = 0;
                    nEnd = nLen;
                    break;
                }
                break;

            case REF_BOOKMARK:
                if( USHRT_MAX == nEnd )
                {
                    // Text steht ueber verschiedene Nodes verteilt.
                    // Gesamten Text oder nur bis zum Ende vom Node?
                    nEnd = pTxtNd->GetTxt().Len();
                }
                nStart = nNumStart;
                // Text steht ueber verschiedene Nodes verteilt.
                // Gesamten Text oder nur bis zum Ende vom Node?
                nEnd = nNumEnd == USHRT_MAX ? nLen : nNumEnd;
                break;

            case REF_OUTLINE:
                nStart = nNumStart;
                nEnd = nNumEnd;
                break;

            case REF_FOOTNOTE:
            case REF_ENDNOTE:
                // die Nummer oder den NumString besorgen
                for( unsigned i = 0; i < pDoc->GetFtnIdxs().Count(); ++i )
                {
                    // die Nummer oder den NumString besorgen
                    sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
                    SwTxtFtn* pFtnIdx;
                    for( n = 0; n < nFtnCnt; ++n )
                        if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
                        {
                            sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
                            break;
                        }
                    nStt = nEnd;        // kein Bereich, der String ist fertig
                    SwTxtFtn* const pFtnIdx = pDoc->GetFtnIdxs()[i];
                    if( nSeqNo == pFtnIdx->GetSeqRefNo() )
                    {
                        sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
                        break;
                    }
                }
                return;

            default:
                nStart = nNumStart;
                nEnd = nNumEnd;
                break;
            }

            if( nStt != nEnd )      // ein Bereich?
            if( nStart != nEnd ) // ein Bereich?
            {
                sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt );
                sTxt = pTxtNd->GetExpandTxt( nStart, nEnd - nStart );

                // alle Sonderzeichen entfernen (durch Blanks ersetzen):
                if( sTxt.Len() )
@@ -396,7 +431,7 @@
        {
            const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0,0,sal_False),
                        *pSave = pFrm;
            while( pFrm && !pFrm->IsInside( nStt ) )
            while( pFrm && !pFrm->IsInside( nNumStart ) )
                pFrm = (SwTxtFrm*)pFrm->GetFollow();

            if( pFrm || 0 != ( pFrm = pSave ))
@@ -443,14 +478,14 @@
            // Node stehen!
            if( pFldTxtAttr->GetpTxtNode() == pTxtNd )
            {
                sTxt = nStt < *pFldTxtAttr->GetStart()
                sTxt = nNumStart < *pFldTxtAttr->GetStart()
                            ? aLocaleData.getAboveWord()
                            : aLocaleData.getBelowWord();
                break;
            }

            sTxt = ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(),
                                    *pTxtNd, nStt )
                                    *pTxtNd, nNumStart )
                        ? aLocaleData.getAboveWord()
                        : aLocaleData.getBelowWord();
        }