[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide' - 160 commits - sw/inc sw/source

Michael Stahl Michael.Stahl at cib.de
Fri May 25 16:52:03 UTC 2018


Rebased ref, commits from common ancestor:
commit fb2744064baa62744bfa9c734a88645c2bf629ba
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Fri May 25 18:41:52 2018 +0200

    sw_redlinehide: fix SwCursorShell::GetContentAtPos() redline code
    
    This calls SwTextFrame::GetCharRect() on the frame where the mouse
    cursor is, with SwPositions that may be in a unrelated SwTextNode.
    
    Bogus positions now triggers asserts, so let's fix it.
    
    Change-Id: Idedb335ffd79c299976ad91b683dfb30cd0ceac2

diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 3864b07e9cf5..a8c8fada8c40 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -1493,11 +1493,17 @@ bool SwCursorShell::GetContentAtPos( const Point& rPt,
 
                         if( pFieldRect && nullptr != ( pFrame = pTextNd->getLayoutFrame( GetLayout(), &aPt ) ) )
                         {
+                            // not sure if this should be limited to one
+                            // paragraph, or mark the entire redline; let's
+                            // leave it limited to one for now...
+                            sal_Int32 nStart;
+                            sal_Int32 nEnd;
+                            pRedl->CalcStartEnd(pTextNd->GetIndex(), nStart, nEnd);
                             //get bounding box of range
                             SwRect aStart;
-                            pFrame->GetCharRect(aStart, *pRedl->Start(), &aTmpState);
+                            pFrame->GetCharRect(aStart, SwPosition(*pTextNd, nStart), &aTmpState);
                             SwRect aEnd;
-                            pFrame->GetCharRect(aEnd, *pRedl->End(), &aTmpState);
+                            pFrame->GetCharRect(aEnd, SwPosition(*pTextNd, nEnd), &aTmpState);
                             if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom())
                             {
                                 aStart.Left(pFrame->getFrameArea().Left());
commit a5d1645f95862938ba565490d09e8d6d128c8b6e
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Fri May 25 14:04:33 2018 +0200

    sw_redlinehide: hyphenation
    
    There's a loop over nodes, calling SwTextNode::Hyphenate() each time.
    Introduce a new class SwInterHyphInfoTextFrame that is used in the
    SwTextFrame functions, and SwTextNode::Hyphenate() converts between
    the 2 types.
    
    Not sure if this will hyphenate a word that is split across nodes in the
    model, but perhaps this is good enough in practice.
    
    Change-Id: I78dec370e15c372284c934d9658b2dd5b3b97ae0

diff --git a/sw/inc/splargs.hxx b/sw/inc/splargs.hxx
index 11b39a10fa3a..efd4c33e6352 100644
--- a/sw/inc/splargs.hxx
+++ b/sw/inc/splargs.hxx
@@ -109,11 +109,15 @@ struct SwSpellArgs : SwArgsBase
 
 class SwInterHyphInfo
 {
-    css::uno::Reference< css::linguistic2::XHyphenatedWord >    xHyphWord;
+    /// output: hyphenated word
+    css::uno::Reference<css::linguistic2::XHyphenatedWord> xHyphWord;
+    /// input: cursor point to locate the frame
     const Point aCursorPos;
 public:
+    /// input: requested range to hyphenate
     sal_Int32 nStart;
     sal_Int32 nEnd;
+    /// output: found word
     sal_Int32 nWordStart;
     sal_Int32 nWordLen;
 
@@ -124,10 +128,6 @@ public:
         , nWordStart(0), nWordLen(0)
     {
     }
-    sal_Int32 GetEnd() const
-    {
-        return nEnd;
-    }
     const Point *GetCursorPos() const
     {
         return aCursorPos.X() || aCursorPos.Y() ? &aCursorPos : nullptr;
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index a139293fec7c..68087a0fb1b6 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -748,6 +748,8 @@ static bool lcl_HyphenateNode( const SwNodePtr& rpNd, void* pArgs )
     SwHyphArgs *pHyphArgs = static_cast<SwHyphArgs*>(pArgs);
     if( pNode )
     {
+        // sw_redlinehide: this will be called once per node for merged nodes;
+        // the fully deleted ones won't have frames so are skipped.
         SwContentFrame* pContentFrame = pNode->getLayoutFrame( pNode->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() );
         if( pContentFrame && !static_cast<SwTextFrame*>(pContentFrame)->IsHiddenNow() )
         {
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index e7c51f082efc..3307378a1026 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -25,6 +25,8 @@
 #include <ndtxt.hxx>
 #include "TextFrameIndex.hxx"
 
+namespace com { namespace sun { namespace star { namespace linguistic2 { class XHyphenatedWord; } } } }
+
 class SwCharRange;
 class SwTextNode;
 class SwTextFormatter;
@@ -46,6 +48,31 @@ class SwScriptInfo;
 
 #define NON_PRINTING_CHARACTER_COLOR Color(0x26, 0x8b, 0xd2)
 
+/// a clone of SwInterHyphInfo, but with TextFrameIndex instead of node index
+class SwInterHyphInfoTextFrame
+{
+private:
+    /// output: hyphenated word
+    css::uno::Reference<css::linguistic2::XHyphenatedWord> m_xHyphWord;
+public:
+    /// input: requested range to hyphenate
+    TextFrameIndex nStart;
+    TextFrameIndex nEnd;
+    /// output: found word
+    TextFrameIndex nWordStart;
+    TextFrameIndex nWordLen;
+
+    SwInterHyphInfoTextFrame(SwTextFrame const& rFrame,
+            SwTextNode const& rNode, SwInterHyphInfo const& rHyphInfo);
+    void UpdateTextNodeHyphInfo(SwTextFrame const& rFrame,
+            SwTextNode const& rNode, SwInterHyphInfo & o_rHyphInfo);
+
+    void SetHyphWord(const css::uno::Reference<css::linguistic2::XHyphenatedWord> &xHW)
+    {
+        m_xHyphWord = xHW;
+    }
+};
+
 namespace sw {
 
 struct Extent
@@ -425,7 +452,7 @@ public:
      * We format a Line for interactive hyphenation
      * @return found
      */
-    bool Hyphenate( SwInterHyphInfo &rInf );
+    bool Hyphenate(SwInterHyphInfoTextFrame & rInf);
 
     /// Test grow
     inline SwTwips GrowTst( const SwTwips nGrow );
diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx
index bf9a6c8af749..ff430b8616d1 100644
--- a/sw/source/core/text/itrform2.hxx
+++ b/sw/source/core/text/itrform2.hxx
@@ -164,7 +164,7 @@ public:
     void RecalcRealHeight();
 
     // We format a line for interactive hyphenation
-    bool Hyphenate( SwInterHyphInfo &rInf );
+    bool Hyphenate(SwInterHyphInfoTextFrame & rInf);
 
     // A special method for QuoVadis texts:
     // nErgo is the page number of the ErgoSum Footnote
diff --git a/sw/source/core/text/txthyph.cxx b/sw/source/core/text/txthyph.cxx
index 929eb95fda2e..dfe2ab713a33 100644
--- a/sw/source/core/text/txthyph.cxx
+++ b/sw/source/core/text/txthyph.cxx
@@ -56,7 +56,7 @@ Reference< XHyphenatedWord >  SwTextFormatInfo::HyphWord(
 /**
  * We format a row for interactive hyphenation
  */
-bool SwTextFrame::Hyphenate( SwInterHyphInfo &rHyphInf )
+bool SwTextFrame::Hyphenate(SwInterHyphInfoTextFrame & rHyphInf)
 {
     vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
     OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"swapped frame at SwTextFrame::Hyphenate" );
@@ -97,7 +97,7 @@ bool SwTextFrame::Hyphenate( SwInterHyphInfo &rHyphInf )
                 aLine.Next();
         }
 
-        const sal_Int32 nEnd = rHyphInf.GetEnd();
+        const TextFrameIndex nEnd = rHyphInf.nEnd;
         while( !bRet && aLine.GetStart() < nEnd )
         {
             bRet = aLine.Hyphenate( rHyphInf );
@@ -124,7 +124,7 @@ void SetParaPortion( SwTextInfo *pInf, SwParaPortion *pRoot )
     pInf->m_pPara = pRoot;
 }
 
-bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
+bool SwTextFormatter::Hyphenate(SwInterHyphInfoTextFrame & rHyphInf)
 {
     SwTextFormatInfo &rInf = GetInfo();
 
@@ -134,7 +134,7 @@ bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
     if( !GetNext() && !rInf.GetTextFly().IsOn() && !m_pFrame->GetFollow() )
         return false;
 
-    sal_Int32 nWrdStart = m_nStart;
+    TextFrameIndex nWrdStart = m_nStart;
 
     // We need to retain the old row
     // E.g.: The attribute for hyphenation was not set, but
@@ -168,16 +168,16 @@ bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
         // HyphPortion in the specified range.
 
         SwLinePortion *pPos = m_pCurr->GetPortion();
-        const sal_Int32 nPamStart = rHyphInf.nStart;
+        const TextFrameIndex nPamStart = rHyphInf.nStart;
         nWrdStart = m_nStart;
-        const sal_Int32 nEnd = rHyphInf.GetEnd();
+        const TextFrameIndex nEnd = rHyphInf.nEnd;
         while( pPos )
         {
             // Either we are above or we are running into a HyphPortion
             // at the end of line or before a Fly.
             if( nWrdStart >= nEnd )
             {
-                nWrdStart = 0;
+                nWrdStart = TextFrameIndex(0);
                 break;
             }
 
@@ -194,13 +194,13 @@ bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
         }
         // When pPos is null, no hyphen position was found.
         if( !pPos )
-            nWrdStart = 0;
+            nWrdStart = TextFrameIndex(0);
     }
     else
         // In case the whole line is zero-length, that's the same situation as
         // above when the portion iteration ends without explicitly breaking
         // from the loop.
-        nWrdStart = 0;
+        nWrdStart = TextFrameIndex(0);
 
     // the old LineLayout is set again ...
     delete m_pCurr;
@@ -212,28 +212,30 @@ bool SwTextFormatter::Hyphenate( SwInterHyphInfo &rHyphInf )
         OSL_ENSURE( IsParaLine(), "SwTextFormatter::Hyphenate: even not the first" );
     }
 
-    if( nWrdStart==0 )
+    if (nWrdStart == TextFrameIndex(0))
         return false;
 
     // nWrdStart contains the position in string that should be hyphenated
     rHyphInf.nWordStart = nWrdStart;
 
-    sal_Int32 nLen = 0;
-    const sal_Int32 nEnd = nWrdStart;
+    TextFrameIndex nLen(0);
+    const TextFrameIndex nEnd = nWrdStart;
 
     // we search forwards
     Reference< XHyphenatedWord > xHyphWord;
 
-    Boundary aBound =
-        g_pBreakIt->GetBreakIter()->getWordBoundary( rInf.GetText(), nWrdStart,
+    Boundary const aBound = g_pBreakIt->GetBreakIter()->getWordBoundary(
+        rInf.GetText(), sal_Int32(nWrdStart),
         g_pBreakIt->GetLocale( rInf.GetFont()->GetLanguage() ), WordType::DICTIONARY_WORD, true );
-    nWrdStart = aBound.startPos;
-    nLen = aBound.endPos - nWrdStart;
-    if ( nLen == 0 )
+    nWrdStart = TextFrameIndex(aBound.startPos);
+    nLen = TextFrameIndex(aBound.endPos) - nWrdStart;
+    if (nLen == TextFrameIndex(0))
         return false;
 
-    OUString aSelText( rInf.GetText().copy(nWrdStart, nLen) );
-    const sal_Int32 nMinTrail = ( nWrdStart + nLen > nEnd ) ? nWrdStart + nLen - nEnd - 1 : 0;
+    OUString const aSelText(rInf.GetText().copy(sal_Int32(nWrdStart), sal_Int32(nLen)));
+    const sal_Int32 nMinTrail = (nWrdStart + nLen > nEnd)
+            ? sal_Int32(nWrdStart + nLen - nEnd) - 1
+            : 0;
 
     //!! rHyphInf.SetHyphWord( ... ) must done here
     xHyphWord = rInf.HyphWord( aSelText, nMinTrail );
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index c226691ec26d..7523293b45ea 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -1614,6 +1614,31 @@ void SwTextFrame::CollectAutoCmplWrds( SwContentNode const * pActNode, sal_Int32
         pNode->SetAutoCompleteWordDirty( false );
 }
 
+SwInterHyphInfoTextFrame::SwInterHyphInfoTextFrame(
+        SwTextFrame const& rFrame, SwTextNode const& rNode,
+        SwInterHyphInfo const& rHyphInfo)
+    : nStart(rFrame.MapModelToView(&rNode, rHyphInfo.nStart))
+    , nEnd(rFrame.MapModelToView(&rNode, rHyphInfo.nEnd))
+    , nWordStart(0)
+    , nWordLen(0)
+{
+}
+
+void SwInterHyphInfoTextFrame::UpdateTextNodeHyphInfo(SwTextFrame const& rFrame,
+        SwTextNode const& rNode, SwInterHyphInfo & o_rHyphInfo)
+{
+    std::pair<SwTextNode const*, sal_Int32> const wordStart(rFrame.MapViewToModel(nWordStart));
+    std::pair<SwTextNode const*, sal_Int32> const wordEnd(rFrame.MapViewToModel(nWordStart+nWordLen));
+    if (wordStart.first != &rNode || wordEnd.first != &rNode)
+    {   // not sure if this can happen since nStart/nEnd are in rNode
+        SAL_WARN("sw.core", "UpdateTextNodeHyphInfo: outside of node");
+        return;
+    }
+    o_rHyphInfo.nWordStart = wordStart.second;
+    o_rHyphInfo.nWordLen = wordEnd.second - wordStart.second;
+    o_rHyphInfo.SetHyphWord(m_xHyphWord);
+}
+
 /// Find the SwTextFrame and call its Hyphenate
 bool SwTextNode::Hyphenate( SwInterHyphInfo &rHyphInf )
 {
@@ -1630,9 +1655,7 @@ bool SwTextNode::Hyphenate( SwInterHyphInfo &rHyphInf )
                 this->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(),
                 rHyphInf.GetCursorPos()));
         });
-    if( pFrame )
-        pFrame = &(pFrame->GetFrameAtOfst( rHyphInf.nStart ));
-    else
+    if (!pFrame)
     {
         // There was a comment here that claimed that the following assertion
         // shouldn't exist as it's triggered by "Trennung ueber Sonderbereiche",
@@ -1640,21 +1663,25 @@ bool SwTextNode::Hyphenate( SwInterHyphInfo &rHyphInf )
         OSL_ENSURE( pFrame, "!SwTextNode::Hyphenate: can't find any frame" );
         return false;
     }
+    SwInterHyphInfoTextFrame aHyphInfo(*pFrame, *this, rHyphInf);
+
+    pFrame = &(pFrame->GetFrameAtOfst( aHyphInfo.nStart ));
 
     while( pFrame )
     {
-        if( pFrame->Hyphenate( rHyphInf ) )
+        if (pFrame->Hyphenate(aHyphInfo))
         {
             // The layout is not robust wrt. "direct formatting"
             // cf. layact.cxx, SwLayAction::TurboAction_(), if( !pCnt->IsValid() ...
             pFrame->SetCompletePaint();
+            aHyphInfo.UpdateTextNodeHyphInfo(*pFrame, *this, rHyphInf);
             return true;
         }
         pFrame = pFrame->GetFollow();
         if( pFrame )
         {
-            rHyphInf.nEnd = rHyphInf.nEnd - (pFrame->GetOfst() - rHyphInf.nStart);
-            rHyphInf.nStart = pFrame->GetOfst();
+            aHyphInfo.nEnd = aHyphInfo.nEnd - (pFrame->GetOfst() - aHyphInfo.nStart);
+            aHyphInfo.nStart = pFrame->GetOfst();
         }
     }
     return false;
commit 1747beec3eb9d68ec11caf91042d8cc511960420
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Fri May 25 10:42:34 2018 +0200

    sw_redlinehide: make SwScanner independent of SwTextNode
    
    Abstract out the GetLang function into a parameter.
    
    SwScanner also uses a ModelToViewHelper but at this place it's used in
    "pass-through" mode which does an identity mapping.
    
    Change-Id: I45557c4e4446d1b4d95a206c414bbb6477593f8a

diff --git a/sw/inc/swscanner.hxx b/sw/inc/swscanner.hxx
index 86f48bb18807..70793def9257 100644
--- a/sw/inc/swscanner.hxx
+++ b/sw/inc/swscanner.hxx
@@ -23,14 +23,16 @@
 #include <i18nlangtag/lang.h>
 #include "modeltoviewhelper.hxx"
 
+#include <functional>
+
 class SwTextNode;
 
 // Helper class that provides consecutively the words of a selected area
 // during spell check
 class SwScanner
 {
+    std::function<LanguageType (sal_Int32, sal_Int32, bool)> m_pGetLangOfChar;
     OUString m_aWord;
-    const SwTextNode& m_rNode;
     const OUString m_aPreDashReplacementText;
     OUString m_aText;
     const LanguageType* m_pLanguage;
@@ -45,6 +47,12 @@ class SwScanner
     bool m_bClip;
 
 public:
+    SwScanner( std::function<LanguageType (sal_Int32, sal_Int32, bool)> pGetLangOfChar,
+               const OUString& rText,
+               const LanguageType* pLang,
+               const ModelToViewHelper& rConvMap,
+               sal_uInt16 nWordType,
+               sal_Int32 nStart, sal_Int32 nEnde, bool bClip = false );
     SwScanner( const SwTextNode& rNd, const OUString& rText,
                const LanguageType* pLang,
                const ModelToViewHelper& rConvMap,
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index b2bf9438f3e3..dbd3f3211945 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1080,9 +1080,22 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
         // we search for connecting opportunities (kashida)
         else if ( bAdjustBlock && i18n::ScriptType::COMPLEX == nScript )
         {
-            SwScanner aScanner( rNode, rText, nullptr, ModelToViewHelper(),
+            // sw_redlinehide: this is the only place that uses SwScanner with
+            // frame text, so we convert to sal_Int32 here
+            std::function<LanguageType (sal_Int32, sal_Int32, bool)> const pGetLangOfCharM(
+                [&pMerged](sal_Int32 const nBegin, sal_uInt16 const nScript, bool const bNoChar)
+                    {
+                        std::pair<SwTextNode const*, sal_Int32> const pos(
+                            sw::MapViewToModel(*pMerged, TextFrameIndex(nBegin)));
+                        return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript);
+                    });
+            std::function<LanguageType (sal_Int32, sal_Int32, bool)> const pGetLangOfChar1(
+                [&rNode](sal_Int32 const nBegin, sal_uInt16 const nScript, bool const bNoChar)
+                    { return rNode.GetLang(nBegin, bNoChar ? 0 : 1, nScript); });
+            auto pGetLangOfChar(pMerged ? pGetLangOfCharM : pGetLangOfChar1);
+            SwScanner aScanner( pGetLangOfChar, rText, nullptr, ModelToViewHelper(),
                                 i18n::WordType::DICTIONARY_WORD,
-                                nLastKashida, nChg );
+                                sal_Int32(nLastKashida), sal_Int32(nChg));
 
             // the search has to be performed on a per word base
             while ( aScanner.NextWord() )
@@ -1235,7 +1248,7 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
 
                 if ( -1 != nKashidaPos )
                 {
-                    m_Kashida.insert(m_Kashida.begin() + nCntKash, nKashidaPos);
+                    m_Kashida.insert(m_Kashida.begin() + nCntKash, TextFrameIndex(nKashidaPos));
                     nCntKash++;
                 }
             } // end of kashida search
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 802ad9901872..c226691ec26d 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -728,7 +728,19 @@ OUString SwTextNode::GetCurWord( sal_Int32 nPos ) const
 SwScanner::SwScanner( const SwTextNode& rNd, const OUString& rText,
     const LanguageType* pLang, const ModelToViewHelper& rConvMap,
     sal_uInt16 nType, sal_Int32 nStart, sal_Int32 nEnde, bool bClp )
-    : m_rNode( rNd )
+    : SwScanner(
+        [&rNd](sal_Int32 const nBegin, sal_uInt16 const nScript, bool const bNoChar)
+            { return rNd.GetLang(nBegin, bNoChar ? 0 : 1, nScript); }
+        , rText, pLang, rConvMap, nType, nStart, nEnde, bClp)
+{
+}
+
+SwScanner::SwScanner(
+    std::function<LanguageType (sal_Int32, sal_Int32, bool)> const pGetLangOfChar,
+    const OUString& rText,
+    const LanguageType* pLang, const ModelToViewHelper& rConvMap,
+    sal_uInt16 nType, sal_Int32 nStart, sal_Int32 nEnde, bool bClp )
+    : m_pGetLangOfChar( pGetLangOfChar )
     , m_aPreDashReplacementText(rText)
     , m_pLanguage( pLang )
     , m_ModelToView( rConvMap )
@@ -775,7 +787,7 @@ SwScanner::SwScanner( const SwTextNode& rNd, const OUString& rText,
     {
         ModelToViewHelper::ModelPosition aModelBeginPos =
             m_ModelToView.ConvertToModelPosition( m_nBegin );
-        m_aCurrentLang = rNd.GetLang( aModelBeginPos.mnPos );
+        m_aCurrentLang = m_pGetLangOfChar(aModelBeginPos.mnPos, 0, true);
     }
 }
 
@@ -837,7 +849,7 @@ bool SwScanner::NextWord()
                     const sal_uInt16 nNextScriptType = g_pBreakIt->GetBreakIter()->getScriptType( m_aText, m_nBegin );
                     ModelToViewHelper::ModelPosition aModelBeginPos =
                         m_ModelToView.ConvertToModelPosition( m_nBegin );
-                    m_aCurrentLang = m_rNode.GetLang( aModelBeginPos.mnPos, 1, nNextScriptType );
+                    m_aCurrentLang = m_pGetLangOfChar(aModelBeginPos.mnPos, nNextScriptType, false);
                 }
 
                 if ( m_nWordType != i18n::WordType::WORD_COUNT )
commit e71d8ea4d3dbc7455877ecd72d869f815528a8d5
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 18:40:28 2018 +0200

    sw_redlinehide: what to do about SwParaPortion::GetDelta()
    
    This has type "long", which is unusal.  Presumably because it needed to
    represent numbers from -USHRT_MAX to +USHRT_MAX back in the day.
    
    Now we have sal_Int32 which happens to be signed and TextFrameIndex,
    but these are always positive currently; would it be too confusing
    to have a potentially negative TextFrameIndex here?
    
    Change-Id: I18c4893d9d24b59e98e9a3994139842ea25ae716

diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 40ed097b1200..176914b69040 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -779,7 +779,7 @@ void SwTextFrame::SetOfst_(TextFrameIndex const nNewOfst)
         SwCharRange &rReformat = pPara->GetReformat();
         rReformat.Start() = TextFrameIndex(0);
         rReformat.Len() = TextFrameIndex(GetText().getLength());
-        pPara->GetDelta() = rReformat.Len();
+        pPara->GetDelta() = sal_Int32(rReformat.Len());
     }
     InvalidateSize();
 }
@@ -1281,7 +1281,7 @@ bool SwTextFrame::FormatLine( SwTextFormatter &rLine, const bool bPrev )
     }
 
     // Calculating the good ol' nDelta
-    pPara->GetDelta() -= long(pNew->GetLen()) - long(nOldLen);
+    pPara->GetDelta() -= sal_Int32(pNew->GetLen()) - sal_Int32(nOldLen);
 
     // Stop!
     if( rLine.IsStop() )
commit 2010a5ed2140efce0f6187d72249b2333a93e3c7
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 18:02:40 2018 +0200

    sw_redlinehide: add SwTextFrame::GetLangOfChar()
    
    The text formatting calls SwTextNode::GetLang(), which is a bit of a
    problem now, but fortunately it calls it only for 0 or 1 character,
    and in that case we can easily indirect this to a single call to
    SwTextNode::Lang() in the right node.
    
    Change-Id: Id151cd6ae277bd2880fc8fc63305110ec2bf88c2

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 11bfdab230fe..e7c51f082efc 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -506,6 +506,9 @@ public:
 
     TextFrameIndex GetDropLen(TextFrameIndex nWishLen) const;
 
+    LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript,
+            bool bNoChar = false) const;
+
     virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override;
     virtual void CheckDirection( bool bVert ) override;
 
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index a629a62c2583..9bcb7bd33fe3 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -369,10 +369,13 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
 
                 // compare current script with script from last "real" character
                 if ( SwFontScript(nScript - 1) != rInf.GetFont()->GetActual() )
-                    aLang = rInf.GetTextFrame()->GetTextNode()->GetLang(
-                        CH_TXTATR_BREAKWORD == cFieldChr ?
-                        nDoNotStepOver :
-                        nLangIndex, 0, nScript );
+                {
+                    aLang = rInf.GetTextFrame()->GetLangOfChar(
+                        CH_TXTATR_BREAKWORD == cFieldChr
+                            ? nDoNotStepOver
+                            : nLangIndex,
+                        nScript, true);
+                }
             }
         }
 
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 186261fda6ff..b89ade928e9e 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -249,7 +249,8 @@ void SwTextMargin::CtorInitTextMargin( SwTextFrame *pNewFrame, SwTextSizeInfo *p
             rSpace.IsAutoFirst() )
         {
             nFirstLineOfs = GetFnt()->GetSize( GetFnt()->GetActual() ).Height();
-            LanguageType aLang = m_pFrame->GetTextNode()->GetLang( 0, 1, css::i18n::ScriptType::ASIAN);
+            LanguageType const aLang = m_pFrame->GetLangOfChar(
+                    TextFrameIndex(0), css::i18n::ScriptType::ASIAN);
             if (aLang != LANGUAGE_KOREAN && aLang != LANGUAGE_JAPANESE)
                 nFirstLineOfs<<=1;
 
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 703591b7feed..8256d458357e 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -92,7 +92,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf,
     if ( nEnd > nPos && ASIAN == nScript )
     {
         LanguageType aLang =
-            rInf.GetTextFrame()->GetTextNode()->GetLang( rInf.GetIdx(), 1, nScript );
+            rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), nScript);
 
         if (!MsLangId::isKorean(aLang))
         {
@@ -130,7 +130,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf,
     if ( nEnd > nPos && COMPLEX == nScript )
     {
         LanguageType aLang =
-            rInf.GetTextFrame()->GetTextNode()->GetLang( rInf.GetIdx(), 1, nScript );
+            rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), nScript);
 
         if ( LANGUAGE_THAI == aLang )
         {
@@ -203,7 +203,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf,
         if( ASIAN == nNextScript )
         {
             LanguageType aLang =
-                rInf.GetTextFrame()->GetTextNode()->GetLang( nPos, 1, nNextScript );
+                rInf.GetTextFrame()->GetLangOfChar(nPos, nNextScript);
 
             if (!MsLangId::isKorean(aLang))
                 ++nCnt;
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 7bcd56a5efd1..df597a2d1513 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -773,6 +773,14 @@ SwDoc const& SwTextFrame::GetDoc() const
     return *GetTextNodeFirst()->GetDoc();
 }
 
+LanguageType SwTextFrame::GetLangOfChar(TextFrameIndex const nIndex,
+        sal_uInt16 const nScript, bool const bNoChar) const
+{
+    // a single character can be mapped uniquely!
+    std::pair<SwTextNode const*, sal_Int32> const pos(MapViewToModel(nIndex));
+    return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript);
+}
+
 void SwTextFrame::ResetPreps()
 {
     if ( GetCacheIdx() != USHRT_MAX )
commit b1814b514717686db381fdfc07f0f13bcc4ce2d5
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 16:09:02 2018 +0200

    sw_redlinehide: SwScriptInfo conversion swcrsr.cxx,edattr.cxx,editsh.cxx
    
    Change-Id: I3676357fbba242fe7f5ed632d704a6704e802217

diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index e84731cd9795..91e9e2e61551 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1593,13 +1593,15 @@ SwCursor::DoSetBidiLevelLeftRight(
         }
         else
         {
-            const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
+            SwTextFrame const* pFrame;
+            const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo(rTNd, &pFrame);
             if ( pSI )
             {
                 const sal_Int32 nMoveOverPos = io_rbLeft ?
                                                ( nPos ? nPos - 1 : 0 ) :
                                                 nPos;
-                SetCursorBidiLevel( pSI->DirType( nMoveOverPos ) );
+                TextFrameIndex nIndex(pFrame->MapModelToView(&rTNd, nMoveOverPos));
+                SetCursorBidiLevel( pSI->DirType(nIndex) );
             }
         }
     }
@@ -1736,8 +1738,9 @@ void SwCursor::DoSetBidiLevelUpDown()
     SwNode& rNode = GetPoint()->nNode.GetNode();
     if ( rNode.IsTextNode() )
     {
+        SwTextFrame const* pFrame;
         const SwScriptInfo* pSI =
-            SwScriptInfo::GetScriptInfo( *rNode.GetTextNode() );
+            SwScriptInfo::GetScriptInfo( *rNode.GetTextNode(), &pFrame );
         if ( pSI )
         {
             SwIndex& rIdx = GetPoint()->nContent;
@@ -1745,8 +1748,9 @@ void SwCursor::DoSetBidiLevelUpDown()
 
             if (nPos && nPos < rNode.GetTextNode()->GetText().getLength())
             {
-                const sal_uInt8 nCurrLevel = pSI->DirType( nPos );
-                const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 );
+                TextFrameIndex const nIndex(pFrame->MapModelToView(rNode.GetTextNode(), nPos));
+                const sal_uInt8 nCurrLevel = pSI->DirType( nIndex );
+                const sal_uInt8 nPrevLevel = pSI->DirType( nIndex - TextFrameIndex(1) );
 
                 if ( nCurrLevel % 2 != nPrevLevel % 2 )
                 {
diff --git a/sw/source/core/edit/edattr.cxx b/sw/source/core/edit/edattr.cxx
index 63f026082b67..df5d6df3b8a9 100644
--- a/sw/source/core/edit/edattr.cxx
+++ b/sw/source/core/edit/edattr.cxx
@@ -307,8 +307,15 @@ std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> SwEditShell
                 const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
                 const sal_Int32 nEnd = (n == nEndNd)
                     ? nEndCnt : pTextNd->GetText().getLength();
-                const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTextNd );
-                sal_uInt8 nScript = pScriptInfo ? pScriptInfo->ScriptType( nStt ) : css::i18n::ScriptType::WEAK;
+                SwTextFrame const* pFrame;
+                const SwScriptInfo *const pScriptInfo =
+                    SwScriptInfo::GetScriptInfo(*pTextNd, &pFrame);
+                TextFrameIndex const iStt(pScriptInfo
+                        ? pFrame->MapModelToView(pTextNd, nStt)
+                        : TextFrameIndex(-1/*invalid, do not use*/));
+                sal_uInt8 nScript = pScriptInfo
+                    ? pScriptInfo->ScriptType(iStt)
+                    : css::i18n::ScriptType::WEAK;
                 nWhich = GetWhichOfScript( nWhich, nScript );
 
                 // item from attribute set
@@ -340,7 +347,9 @@ std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> SwEditShell
                         if( *pAttrEnd <= nStt )
                             continue;
 
-                        nScript = pScriptInfo ? pScriptInfo->ScriptType( nStt ) : css::i18n::ScriptType::WEAK;
+                        nScript = pScriptInfo
+                            ? pScriptInfo->ScriptType(iStt)
+                            : css::i18n::ScriptType::WEAK;
                         nWhich = GetWhichOfScript( nWhich, nScript );
                         const SfxItemSet* pAutoSet = CharFormat::GetItemSet( pHt->GetAttr() );
                         if( pAutoSet )
@@ -651,7 +660,9 @@ SvtScriptType SwEditShell::GetScriptType() const
                 if( pTNd )
                 {
                     // try to get SwScriptInfo
-                    const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
+                    SwTextFrame const* pFrame;
+                    const SwScriptInfo *const pScriptInfo =
+                        SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
 
                     sal_Int32 nPos = pStt->nContent.GetIndex();
                     //Task 90448: we need the scripttype of the previous
@@ -667,9 +678,9 @@ SvtScriptType SwEditShell::GetScriptType() const
 
                     if (!pTNd->GetText().isEmpty())
                     {
-                        nScript = pScriptInfo ?
-                                  pScriptInfo->ScriptType( nPos ) :
-                                  g_pBreakIt->GetBreakIter()->getScriptType( pTNd->GetText(), nPos );
+                        nScript = pScriptInfo
+                            ? pScriptInfo->ScriptType(pFrame->MapModelToView(pTNd, nPos))
+                            : g_pBreakIt->GetBreakIter()->getScriptType( pTNd->GetText(), nPos );
                     }
                     else
                         nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
@@ -689,7 +700,9 @@ SvtScriptType SwEditShell::GetScriptType() const
                         const OUString& rText = pTNd->GetText();
 
                         // try to get SwScriptInfo
-                        const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
+                        SwTextFrame const* pFrame;
+                        const SwScriptInfo *const pScriptInfo =
+                            SwScriptInfo::GetScriptInfo(*pTNd, &pFrame);
 
                         sal_Int32 nChg = aIdx == pStt->nNode
                                                 ? pStt->nContent.GetIndex()
@@ -706,8 +719,11 @@ SvtScriptType SwEditShell::GetScriptType() const
                         sal_uInt16 nScript;
                         while( nChg < nEndPos )
                         {
+                            TextFrameIndex const iChg(pScriptInfo
+                                    ? pFrame->MapModelToView(pTNd, nChg)
+                                    : TextFrameIndex(-1/*invalid, do not use*/));
                             nScript = pScriptInfo ?
-                                      pScriptInfo->ScriptType( nChg ) :
+                                      pScriptInfo->ScriptType( iChg ) :
                                       g_pBreakIt->GetBreakIter()->getScriptType(
                                                                 rText, nChg );
 
@@ -721,10 +737,20 @@ SvtScriptType SwEditShell::GetScriptType() const
 
                             sal_Int32 nFieldPos = nChg+1;
 
-                            nChg = pScriptInfo ?
-                                   pScriptInfo->NextScriptChg( nChg ) :
-                                   g_pBreakIt->GetBreakIter()->endOfScript(
+                            if (pScriptInfo)
+                            {
+                                std::pair<SwTextNode*, sal_Int32> const tmp(
+                                    pFrame->MapViewToModel(
+                                        pScriptInfo->NextScriptChg(iChg)));
+                                nChg = (tmp.first == pTNd)
+                                    ? tmp.second
+                                    : pTNd->Len();
+                            }
+                            else
+                            {
+                                nChg = g_pBreakIt->GetBreakIter()->endOfScript(
                                                     rText, nChg, nScript );
+                            }
 
                             nFieldPos = rText.indexOf(
                                             CH_TXTATR_BREAKWORD, nFieldPos);
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index d04548b7eb23..e3f443b25eec 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -145,7 +145,9 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
                 SwScriptInfo aScriptInfo;
                 aScriptInfo.InitScriptInfo(static_cast<SwTextNode&>(rNode),
                         pFrame->GetMergedPara(), pFrame->IsRightToLeft());
-                nLevel = aScriptInfo.DirType( nPrevPos );
+                TextFrameIndex const iPrevPos(pFrame->MapModelToView(
+                            &static_cast<SwTextNode&>(rNode), nPrevPos));
+                nLevel = aScriptInfo.DirType( iPrevPos );
             }
             else
             {
@@ -154,7 +156,9 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
                     // mystery why this doesn't use the other overload?
                     pSI->InitScriptInfo(static_cast<SwTextNode&>(rNode), pFrame->GetMergedPara());
                 }
-                nLevel = pSI->DirType( nPrevPos );
+                TextFrameIndex const iPrevPos(pFrame->MapModelToView(
+                            &static_cast<SwTextNode&>(rNode), nPrevPos));
+                nLevel = pSI->DirType(iPrevPos);
             }
 
             pTmpCursor->SetCursorBidiLevel( nLevel );
commit 39a50394e29ecfd25b2b9b45952f5495330a75b5
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 15:59:10 2018 +0200

    sw_redlinehide: SwScriptInfo::GetScriptInfo() should return frame too
    
    The SwScriptInfo comes from the frame, and if both are used together
    they have to match.
    
    Change-Id: I3de0754d9ff316180fc04708889886684d6868e5

diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index b5f8dbc1cee8..d04548b7eb23 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -129,14 +129,16 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
             if ( nPrevPos )
                 --nPrevPos;
 
-            SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( static_cast<SwTextNode&>(rNode), true );
+            SwTextFrame const* pFrame;
+            SwScriptInfo *const pSI = SwScriptInfo::GetScriptInfo(
+                    static_cast<SwTextNode&>(rNode), &pFrame, true);
 
             sal_uInt8 nLevel = 0;
             if ( ! pSI )
             {
                 // seems to be an empty paragraph.
                 Point aPt; // why ???
-                SwTextFrame *const pFrame = static_cast<SwTextFrame*>(
+                pFrame = static_cast<SwTextFrame*>(
                         static_cast<SwTextNode&>(rNode).getLayoutFrame(
                             GetLayout(), &aPt, pTmpCursor->GetPoint(), false));
 
@@ -149,10 +151,6 @@ void SwEditShell::Insert2(const OUString &rStr, const bool bForceExpandHints )
             {
                 if (TextFrameIndex(COMPLETE_STRING) != pSI->GetInvalidityA())
                 {
-                    // note: if pSI was found, there must be a frame
-                    SwTextFrame *const pFrame = static_cast<SwTextFrame*>(
-                        static_cast<SwTextNode&>(rNode).getLayoutFrame(
-                            GetLayout(), nullptr, pTmpCursor->GetPoint(), false));
                     // mystery why this doesn't use the other overload?
                     pSI->InitScriptInfo(static_cast<SwTextNode&>(rNode), pFrame->GetMergedPara());
                 }
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index a027b123ebdf..9386f1309e8e 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -28,6 +28,7 @@
 #include "TextFrameIndex.hxx"
 
 class SwTextNode;
+class SwTextFrame;
 class Point;
 class MultiSelection;
 typedef std::vector< sal_Int32 > PositionList;
@@ -366,8 +367,11 @@ public:
                                   TextFrameIndex nLen, LanguageType aLang,
                                   long nSpaceAdd, bool bIsSpaceStop );
 
+    /// return a frame for the node, ScriptInfo is its member...
+    /// (many clients need both frame and SI, and both have to match)
     static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
-                                        bool bAllowInvalid = false );
+                                        SwTextFrame const** o_pFrame = nullptr,
+                                        bool bAllowInvalid = false);
 
     SwFontScript WhichFont(TextFrameIndex nIdx) const;
     static SwFontScript WhichFont(sal_Int32 nIdx, OUString const & rText);
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index b7a00c02fdbb..b2bf9438f3e3 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -2081,7 +2081,8 @@ TextFrameIndex SwScriptInfo::ThaiJustify( const OUString& rText, long* pKernArra
 }
 
 SwScriptInfo* SwScriptInfo::GetScriptInfo( const SwTextNode& rTNd,
-                                           bool bAllowInvalid )
+                                           SwTextFrame const**const o_ppFrame,
+                                           bool const bAllowInvalid)
 {
     SwIterator<SwTextFrame,SwTextNode> aIter( rTNd );
     SwScriptInfo* pScriptInfo = nullptr;
@@ -2093,7 +2094,13 @@ SwScriptInfo* SwScriptInfo::GetScriptInfo( const SwTextNode& rTNd,
         {
             if (bAllowInvalid ||
                 TextFrameIndex(COMPLETE_STRING) == pScriptInfo->GetInvalidityA())
+            {
+                if (o_ppFrame)
+                {
+                    *o_ppFrame = pLast;
+                }
                 break;
+            }
             pScriptInfo = nullptr;
         }
     }
commit bdb2002abca24432808e41dc4da01573388740e4
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 15:56:19 2018 +0200

    sw_redlinehide: SwScriptInfo conversion in itradj.cxx
    
    Have to reinterpret_cast arrays here to pass them to VCL.
    
    Change-Id: Ia0d1b9ab159e55bae01f1cabf3c137a9c8676c79

diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx
index 524454d7a093..428c8d93fe51 100644
--- a/sw/source/core/text/itradj.cxx
+++ b/sw/source/core/text/itradj.cxx
@@ -131,8 +131,8 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf,
 
     // kashida positions found in SwScriptInfo are not necessarily valid in every font
     // if two characters are replaced by a ligature glyph, there will be no place for a kashida
-    std::unique_ptr<sal_Int32[]> pKashidaPos( new sal_Int32[ rKashidas ] );
-    std::unique_ptr<sal_Int32[]> pKashidaPosDropped( new sal_Int32[ rKashidas ] );
+    std::unique_ptr<TextFrameIndex[]> pKashidaPos(new TextFrameIndex[rKashidas]);
+    std::unique_ptr<TextFrameIndex[]> pKashidaPosDropped(new TextFrameIndex[rKashidas]);
     rSI.GetKashidaPositions ( nIdx, rItr.GetLength(), pKashidaPos.get() );
     sal_Int32 nKashidaIdx = 0;
     while ( rKashidas && nIdx < nEnd )
@@ -142,7 +142,7 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf,
 
         // is there also a script change before?
         // if there is, nNext should point to the script change
-        sal_Int32 nNextScript = rSI.NextScriptChg( nIdx );
+        TextFrameIndex const nNextScript = rSI.NextScriptChg( nIdx );
         if( nNextScript < nNext )
             nNext = nNextScript;
 
@@ -161,15 +161,17 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf,
             {
                 ComplexTextLayoutFlags nOldLayout = rInf.GetOut()->GetLayoutMode();
                 rInf.GetOut()->SetLayoutMode ( nOldLayout | ComplexTextLayoutFlags::BiDiRtl );
-                nKashidasDropped = rInf.GetOut()->ValidateKashidas ( rInf.GetText(), nIdx, nNext - nIdx,
-                                               nKashidasInAttr, pKashidaPos.get() + nKashidaIdx,
-                                               pKashidaPosDropped.get() );
+                nKashidasDropped = rInf.GetOut()->ValidateKashidas(
+                    rInf.GetText(), sal_Int32(nIdx), sal_Int32(nNext - nIdx),
+                    nKashidasInAttr,
+                    reinterpret_cast<sal_Int32*>(pKashidaPos.get() + nKashidaIdx),
+                    reinterpret_cast<sal_Int32*>(pKashidaPosDropped.get()));
                 rInf.GetOut()->SetLayoutMode ( nOldLayout );
                 if ( nKashidasDropped )
                 {
                     rSI.MarkKashidasInvalid(nKashidasDropped, pKashidaPosDropped.get());
                     rKashidas -= nKashidasDropped;
-                    nGluePortion -= nKashidasDropped;
+                    nGluePortion -= TextFrameIndex(nKashidasDropped);
                 }
             }
             nKashidaIdx += nKashidasInAttr;
@@ -199,11 +201,11 @@ static bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTextSizeInfo& rInf, SwT
 
             // is there also a script change before?
             // if there is, nNext should point to the script change
-            sal_Int32 nNextScript = rSI.NextScriptChg( nIdx );
+            TextFrameIndex const nNextScript = rSI.NextScriptChg( nIdx );
             if( nNextScript < nNext )
                nNext = nNextScript;
 
-            if ( nNext == COMPLETE_STRING || nNext > nEnd )
+            if (nNext == TextFrameIndex(COMPLETE_STRING) || nNext > nEnd)
                 nNext = nEnd;
             sal_Int32 nKashidasInAttr = rSI.KashidaJustify ( nullptr, nullptr, nIdx, nNext - nIdx );
 
commit c2cc7fc3217e6bc84666406e740337826b1f649f
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 14:26:53 2018 +0200

    sw_redlinehide: add a SwTextFrame::GetDropLen()
    
    Copy the SwTextNode::GetDropLen, as it can't be used in case the
    drop-text would include a delete redline, but the SwTextNode one is
    apparently needed by the WW8 filter.
    
    Change-Id: I26a8a15e977120d601d87a76d712005e2888b713

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 14e648f39abb..11bfdab230fe 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -504,6 +504,8 @@ public:
      */
     SwTwips GetFootnoteLine( const SwTextFootnote *pFootnote ) const;
 
+    TextFrameIndex GetDropLen(TextFrameIndex nWishLen) const;
+
     virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override;
     virtual void CheckDirection( bool bVert ) override;
 
diff --git a/sw/source/core/text/txtdrop.cxx b/sw/source/core/text/txtdrop.cxx
index 2f8ca9d0decf..85138e2cd35f 100644
--- a/sw/source/core/text/txtdrop.cxx
+++ b/sw/source/core/text/txtdrop.cxx
@@ -169,6 +169,61 @@ sal_Int32 SwTextNode::GetDropLen( sal_Int32 nWishLen ) const
     return i;
 }
 
+/// nWishLen = 0 indicates that we want a whole word
+TextFrameIndex SwTextFrame::GetDropLen(TextFrameIndex const nWishLen) const
+{
+    TextFrameIndex nEnd(GetText().getLength());
+    if (nWishLen && nWishLen < nEnd)
+        nEnd = nWishLen;
+
+    if (! nWishLen)
+    {
+        // find first word
+        const SwAttrSet& rAttrSet = GetTextNodeForParaProps()->GetSwAttrSet();
+        const sal_uInt16 nTextScript = g_pBreakIt->GetRealScriptOfText(GetText(), 0);
+
+        LanguageType eLanguage;
+
+        switch ( nTextScript )
+        {
+        case i18n::ScriptType::ASIAN :
+            eLanguage = rAttrSet.GetCJKLanguage().GetLanguage();
+            break;
+        case i18n::ScriptType::COMPLEX :
+            eLanguage = rAttrSet.GetCTLLanguage().GetLanguage();
+            break;
+        default :
+            eLanguage = rAttrSet.GetLanguage().GetLanguage();
+            break;
+        }
+
+        Boundary aBound = g_pBreakIt->GetBreakIter()->getWordBoundary(
+            GetText(), 0, g_pBreakIt->GetLocale(eLanguage),
+            WordType::DICTIONARY_WORD, true );
+
+        nEnd = TextFrameIndex(aBound.endPos);
+    }
+
+    TextFrameIndex i(0);
+    for ( ; i < nEnd; ++i)
+    {
+        sal_Unicode const cChar = GetText()[sal_Int32(i)];
+        if (CH_TAB == cChar || CH_BREAK == cChar ||
+            CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar)
+        {
+#ifndef NDEBUG
+            if (CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar)
+            {
+                std::pair<SwTextNode const*, sal_Int32> const pos(MapViewToModel(i));
+                assert(pos.first->GetTextAttrForCharAt(pos.second) != nullptr);
+            }
+#endif
+            break;
+        }
+    }
+    return i;
+}
+
 /**
  * If a dropcap is found the return value is true otherwise false. The
  * drop cap sizes passed back by reference are font height, drop height
@@ -510,7 +565,7 @@ SwDropPortion *SwTextFormatter::NewDropPortion( SwTextFormatInfo &rInf )
         return nullptr;
 
     TextFrameIndex nPorLen(pDropFormat->GetWholeWord() ? 0 : pDropFormat->GetChars());
-    nPorLen = m_pFrame->GetTextNode()->GetDropLen( nPorLen );
+    nPorLen = m_pFrame->GetDropLen( nPorLen );
     if( !nPorLen )
     {
         ClearDropFormat();
commit 1794464d58e6d5acd5156c0b8c1d1fe86159d6b8
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 14:02:53 2018 +0200

    sw_redlinehide: SwScriptInfo conversion in txtdrop.cxx
    
    Change-Id: I65a8c7a1fc6a16dc602dfb73f8a17424ab01f162

diff --git a/sw/source/core/text/txtdrop.cxx b/sw/source/core/text/txtdrop.cxx
index b1ff0ec20386..2f8ca9d0decf 100644
--- a/sw/source/core/text/txtdrop.cxx
+++ b/sw/source/core/text/txtdrop.cxx
@@ -509,7 +509,7 @@ SwDropPortion *SwTextFormatter::NewDropPortion( SwTextFormatInfo &rInf )
     if( !pDropFormat )
         return nullptr;
 
-    sal_Int32 nPorLen = pDropFormat->GetWholeWord() ? 0 : pDropFormat->GetChars();
+    TextFrameIndex nPorLen(pDropFormat->GetWholeWord() ? 0 : pDropFormat->GetChars());
     nPorLen = m_pFrame->GetTextNode()->GetDropLen( nPorLen );
     if( !nPorLen )
     {
@@ -549,7 +549,7 @@ SwDropPortion *SwTextFormatter::NewDropPortion( SwTextFormatInfo &rInf )
 
     // build DropPortionParts:
     OSL_ENSURE( ! rInf.GetIdx(), "Drop Portion not at 0 position!" );
-    sal_Int32 nNextChg = 0;
+    TextFrameIndex nNextChg(0);
     const SwCharFormat* pFormat = pDropFormat->GetCharFormat();
     SwDropPortionPart* pCurrPart = nullptr;
 
@@ -570,8 +570,8 @@ SwDropPortion *SwTextFormatter::NewDropPortion( SwTextFormatInfo &rInf )
         pTmpFnt->SetVertical( 0, rInf.GetTextFrame()->IsVertical() );
 
         // find next attribute change / script change
-        const sal_Int32 nTmpIdx = nNextChg;
-        sal_Int32 nNextAttr = std::min( GetNextAttr(), rInf.GetText().getLength() );
+        const TextFrameIndex nTmpIdx = nNextChg;
+        TextFrameIndex nNextAttr = GetNextAttr();
         nNextChg = m_pScriptInfo->NextScriptChg( nTmpIdx );
         if( nNextChg > nNextAttr )
             nNextChg = nNextAttr;
commit 0e9da5af4c8449fe20590a0d4a2d4a3ef3032d8b
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 13:18:53 2018 +0200

    sw_redlinehide: SwScriptInfo conversion in itrform2.cxx
    
    Change-Id: Ia591961a27bed76fb762cfe9060f245b31ca2e01

diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 4b3455c79dbe..4080c85ce0ae 100755
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -603,10 +603,10 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
             {
                 // The distance between two different scripts is set
                 // to 20% of the fontheight.
-                sal_Int32 nTmp = rInf.GetIdx() + pPor->GetLen();
-                if( nTmp == m_pScriptInfo->NextScriptChg( nTmp - 1 ) &&
-                    nTmp != rInf.GetText().getLength() &&
-                    (m_pScriptInfo->ScriptType(nTmp - 1) == css::i18n::ScriptType::ASIAN ||
+                TextFrameIndex const nTmp = rInf.GetIdx() + pPor->GetLen();
+                if (nTmp == m_pScriptInfo->NextScriptChg(nTmp - TextFrameIndex(1)) &&
+                    nTmp != TextFrameIndex(rInf.GetText().getLength()) &&
+                    (m_pScriptInfo->ScriptType(nTmp - TextFrameIndex(1)) == css::i18n::ScriptType::ASIAN ||
                      m_pScriptInfo->ScriptType(nTmp) == css::i18n::ScriptType::ASIAN) )
                 {
                     const sal_uInt16 nDist = static_cast<sal_uInt16>(rInf.GetFont()->GetHeight()/5);
@@ -616,8 +616,8 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
                         // we do not want a kerning portion if any end
                         // would be a punctuation character
                         const CharClass& rCC = GetAppCharClass();
-                        if ( rCC.isLetterNumeric( rInf.GetText(), nTmp - 1 ) &&
-                             rCC.isLetterNumeric( rInf.GetText(), nTmp ) )
+                        if (rCC.isLetterNumeric(rInf.GetText(), sal_Int32(nTmp) - 1)
+                            && rCC.isLetterNumeric(rInf.GetText(), sal_Int32(nTmp)))
                         {
                             // does the kerning portion still fit into the line?
                             if ( rInf.X() + pPor->Width() + nDist <= rInf.Width() )
@@ -632,13 +632,14 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
 
         if ( bHasGrid && pGrid->IsSnapToChars() && pPor != pGridKernPortion && ! pMulti && ! pPor->InTabGrp() )
         {
-            sal_Int32 nTmp = rInf.GetIdx() + pPor->GetLen();
+            TextFrameIndex const nTmp = rInf.GetIdx() + pPor->GetLen();
             const SwTwips nRestWidth = rInf.Width() - rInf.X() - pPor->Width();
 
             const SwFontScript nCurrScript = m_pFont->GetActual(); // pScriptInfo->ScriptType( rInf.GetIdx() );
-            const SwFontScript nNextScript = nTmp >= rInf.GetText().getLength() ?
-                                     SwFontScript::CJK :
-                                     m_pScriptInfo->WhichFont(nTmp);
+            const SwFontScript nNextScript =
+                nTmp >= TextFrameIndex(rInf.GetText().getLength())
+                    ? SwFontScript::CJK
+                    : m_pScriptInfo->WhichFont(nTmp);
 
             // snap non-asian text to grid if next portion is ASIAN or
             // there are no more portions in this line
@@ -950,11 +951,11 @@ SwTextPortion *SwTextFormatter::NewTextPortion( SwTextFormatInfo &rInf )
     TextFrameIndex nNextChg = std::min(nNextAttr, TextFrameIndex(rInf.GetText().getLength()));
 
     // end of script type:
-    const sal_Int32 nNextScript = m_pScriptInfo->NextScriptChg( rInf.GetIdx() );
+    const TextFrameIndex nNextScript = m_pScriptInfo->NextScriptChg(rInf.GetIdx());
     nNextChg = std::min( nNextChg, nNextScript );
 
     // end of direction:
-    const sal_Int32 nNextDir = m_pScriptInfo->NextDirChg( rInf.GetIdx() );
+    const TextFrameIndex nNextDir = m_pScriptInfo->NextDirChg(rInf.GetIdx());
     nNextChg = std::min( nNextChg, nNextDir );
 
     // Turbo boost:
commit 4388b4f6f29e75f184c5dc1b37c1e6d9ef663eda
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 12:57:53 2018 +0200

    sw_redlinehide: convert SwFieldPortion::CheckScript()
    
    Change-Id: I85dd0a194e0a406c4a2af51676c996fcfc558961

diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index a1d5e72f584f..d40ff3ed3dc0 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -211,9 +211,10 @@ void SwFieldPortion::CheckScript( const SwTextSizeInfo &rInf )
     // nNextScriptChg will be evaluated during SwFieldPortion::Format()
 
     if (nChg < aText.getLength() && nChg >= 0)
-        m_nNextScriptChg = g_pBreakIt->GetBreakIter()->endOfScript( aText, nChg, nScript );
+        m_nNextScriptChg = TextFrameIndex(
+                g_pBreakIt->GetBreakIter()->endOfScript(aText, nChg, nScript));
     else
-        m_nNextScriptChg = aText.getLength();
+        m_nNextScriptChg = TextFrameIndex(aText.getLength());
 
     SwFontScript nTmp;
     switch ( nScript ) {
@@ -238,7 +239,7 @@ void SwFieldPortion::CheckScript( const SwTextSizeInfo &rInf )
         UBiDiLevel nCurrDir;
         ubidi_getLogicalRun( pBidi, 0, &nEnd, &nCurrDir );
         ubidi_close( pBidi );
-        const sal_Int32 nNextDirChg = nEnd;
+        const TextFrameIndex nNextDirChg(nEnd);
         m_nNextScriptChg = std::min( m_nNextScriptChg, nNextDirChg );
 
         // #i89825# change the script type also to CTL
commit de8d33eb524458609efb8654be167de58027e703
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 12:30:07 2018 +0200

    sw_redlinehide: disambiguate SwScriptInfo::GetBoundsOfHiddenRange()
    
    Remove the "fast-path" from the static to the member function,
    as it won't work with merged paragraphs.
    
    This was the only caller that used the PositionList parameter, so remove
    that.
    
    Change-Id: Ide00cccca4bbc5cd2447477c34cb7b04f9eccfc6

diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 8ab6e7643598..a027b123ebdf 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -223,7 +223,7 @@ public:
                                         sal_Int32& rnStartPos, sal_Int32& rnEndPos,
                                         PositionList* pList = nullptr );
     bool GetBoundsOfHiddenRange(TextFrameIndex nPos, TextFrameIndex & rnStartPos,
-                                TextFrameIndex & rnEndPos, PositionList* pList = nullptr) const;
+                                TextFrameIndex & rnEndPos) const;
 
     static bool IsInHiddenRange( const SwTextNode& rNode, sal_Int32 nPos );
 
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index e11272ac25a0..b7a00c02fdbb 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1521,6 +1521,8 @@ bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nP
         }
     }
 
+    // sw_redlinehide: this won't work if it's merged
+#if 0
     const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rNode );
     if ( pSI )
     {
@@ -1533,6 +1535,7 @@ bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nP
         rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
     }
     else
+#endif
     {
 
         // No valid SwScriptInfo Object, we have to do it the hard way:
@@ -1576,8 +1579,7 @@ bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTextNode& rNode, sal_Int32 nP
 }
 
 bool SwScriptInfo::GetBoundsOfHiddenRange(TextFrameIndex nPos,
-        TextFrameIndex & rnStartPos, TextFrameIndex & rnEndPos,
-        PositionList *const pList) const
+        TextFrameIndex & rnStartPos, TextFrameIndex & rnEndPos) const
 {
     rnStartPos = TextFrameIndex(COMPLETE_STRING);
     rnEndPos = TextFrameIndex(0);
@@ -1598,15 +1600,6 @@ bool SwScriptInfo::GetBoundsOfHiddenRange(TextFrameIndex nPos,
         }
     }
 
-    if ( pList )
-    {
-        for( size_t nX = 0; nX < nEnd; ++nX )
-        {
-            pList->push_back( GetHiddenChg( nX++ ) );
-            pList->push_back( GetHiddenChg( nX ) );
-        }
-    }
-
     return CountHiddenChg() > 0;
 }
 
commit c2b8106dd6a11abb96c8387432a147498f383629
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 12:27:14 2018 +0200

    sw_redlinehide: SwScriptInfo::InitScriptInfo() init m_HiddenChg
    
    ... in the MergedPara case. For now, keep the CalcHiddenRanges()
    per-node, and rely on it marking all redlines as "visible" so
    the range comparison is quite simple.
    
    Change-Id: Ida0435800caf3efdea963079b756f47cc78e95a5

diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 7ec772a020a9..e11272ac25a0 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -720,19 +720,77 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
 
     // HIDDEN TEXT INFORMATION
 
-    Range aRange( 0, !rText.isEmpty() ? rText.getLength() - 1 : 0 );
-    MultiSelection aHiddenMulti( aRange );
-    CalcHiddenRanges( rNode, aHiddenMulti );
-
     m_HiddenChg.clear();
-    for( sal_Int32 i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
+    if (pMerged)
+    {
+        SwTextNode const* pNode(nullptr);
+        TextFrameIndex nOffset(0);
+        for (auto iter = pMerged->extents.begin(); iter != pMerged->extents.end(); ++iter)
+        {
+            if (iter->pNode == pNode)
+            {
+                nOffset += TextFrameIndex(iter->nEnd - iter->nStart);
+                continue; // skip extents at end of previous node
+            }
+            pNode = iter->pNode;
+            Range aRange( 0, pNode->Len() > 0 ? pNode->Len() - 1 : 0 );
+            MultiSelection aHiddenMulti( aRange );
+            CalcHiddenRanges( *pNode, aHiddenMulti );
+
+            for (sal_Int32 i = 0; i < aHiddenMulti.GetRangeCount(); ++i)
+            {
+                const Range& rRange = aHiddenMulti.GetRange( i );
+                const sal_Int32 nStart = rRange.Min();
+                const sal_Int32 nEnd = rRange.Max() + 1;
+
+                while (true)
+                {
+                    // because of the selectRedLineDeleted call, never overlaps
+                    // extents, must be contained inside one extent
+                    assert(!(iter->nStart <= nStart && nStart < iter->nEnd && iter->nEnd < nEnd));
+                    assert(!(nStart < iter->nStart && iter->nStart < nEnd && nEnd <= iter->nEnd));
+                    if (iter->nStart <= nStart && nEnd <= iter->nEnd)
+                    {
+                        if (iter->nStart == nStart && !m_HiddenChg.empty()
+                            && m_HiddenChg.back() == nOffset)
+                        {
+                            // previous one went until end of extent, extend it
+                            m_HiddenChg.back() += TextFrameIndex(nEnd - iter->nStart);
+                        }
+                        else // new one
+                        {
+                            m_HiddenChg.push_back(nOffset + TextFrameIndex(nStart - iter->nStart));
+                            m_HiddenChg.push_back(nOffset + TextFrameIndex(nEnd - iter->nStart));
+                        }
+                        break;
+                    }
+                    else
+                    {
+                        nOffset += TextFrameIndex(iter->nEnd - iter->nStart);
+                        ++iter;
+                        // because selectRedLineDeleted, must find it in pNode
+                        assert(iter != pMerged->extents.end());
+                        assert(iter->pNode == pNode);
+                    }
+                }
+            }
+        }
+    }
+    else
     {
-        const Range& rRange = aHiddenMulti.GetRange( i );
-        const sal_Int32 nStart = rRange.Min();
-        const sal_Int32 nEnd = rRange.Max() + 1;
+        Range aRange( 0, !rText.isEmpty() ? rText.getLength() - 1 : 0 );
+        MultiSelection aHiddenMulti( aRange );
+        CalcHiddenRanges( rNode, aHiddenMulti );
 
-        m_HiddenChg.push_back( nStart );
-        m_HiddenChg.push_back( nEnd );
+        for (sal_Int32 i = 0; i < aHiddenMulti.GetRangeCount(); ++i)
+        {
+            const Range& rRange = aHiddenMulti.GetRange( i );
+            const sal_Int32 nStart = rRange.Min();
+            const sal_Int32 nEnd = rRange.Max() + 1;
+
+            m_HiddenChg.push_back( TextFrameIndex(nStart) );
+            m_HiddenChg.push_back( TextFrameIndex(nEnd) );
+        }
     }
 
     // SCRIPT AND SCRIPT RELATED INFORMATION
commit 3a3d6b70e3780dbe971fafa572a444675237a41f
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 10:44:06 2018 +0200

    sw_redlinehide: convert SwSubFont::DrawText_ to static SwScriptInfo
    
    Change-Id: I7bdcb5f787b6a82def4f7ca5aca29a16b6881e38

diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx
index 82adaaa4b51c..ed23fff22623 100644
--- a/sw/source/core/txtnode/swfont.cxx
+++ b/sw/source/core/txtnode/swfont.cxx
@@ -1213,20 +1213,23 @@ void SwSubFont::DrawText_( SwDrawTextInfo &rInf, const bool bGrey )
         long nSpace = 0;
         if( rInf.GetSpace() )
         {
-            sal_Int32 nTmpEnd = nOldIdx + nOldLen;
-            if (nTmpEnd > oldStr.getLength())
-                nTmpEnd = oldStr.getLength();
+            TextFrameIndex nTmpEnd = nOldIdx + nOldLen;
+            if (nTmpEnd > TextFrameIndex(oldStr.getLength()))
+                nTmpEnd = TextFrameIndex(oldStr.getLength());
 
             const SwScriptInfo* pSI = rInf.GetScriptInfo();
 
             const bool bAsianFont =
                 ( rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() );
-            for( sal_Int32 nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp )
+            for (TextFrameIndex nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp)
             {
-                if (CH_BLANK == oldStr[nTmp] || bAsianFont ||
-                    ( nTmp + 1 < oldStr.getLength() && pSI &&
-                      i18n::ScriptType::ASIAN == pSI->ScriptType( nTmp + 1 ) ) )
+                if (CH_BLANK == oldStr[sal_Int32(nTmp)] || bAsianFont ||
+                    (nTmp + TextFrameIndex(1) < TextFrameIndex(oldStr.getLength())
+                     && pSI
+                     && i18n::ScriptType::ASIAN == pSI->ScriptType(nTmp + TextFrameIndex(1))))
+                {
                     ++nSpace;
+                }
             }
 
             // if next portion if a hole portion we do not consider any
commit cd6057ac59877e126887ba83c4958a2ffc020d93
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 10:40:59 2018 +0200

    ... impl.
    
    Change-Id: I17393f2d4ea3dda63ab2becda5f44f959248b538

diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 49cb28187867..7ec772a020a9 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1814,8 +1814,8 @@ bool SwScriptInfo::IsArabicText(const OUString& rText,
 
     // go forward if current position does not hold a regular character:
     const CharClass& rCC = GetAppCharClass();
-    sal_Int32 nIdx = nStt;
-    const sal_Int32 nEnd = nStt + nLen;
+    sal_Int32 nIdx = sal_Int32(nStt);
+    const sal_Int32 nEnd = sal_Int32(nStt + nLen);
     while ( nIdx < nEnd && !rCC.isLetterNumeric( rText, nIdx ) )
     {
         ++nIdx;
@@ -1996,25 +1996,25 @@ TextFrameIndex SwScriptInfo::ThaiJustify( const OUString& rText, long* pKernArra
                                      TextFrameIndex nNumberOfBlanks,
                                      long nSpaceAdd )
 {
-    SAL_WARN_IF( nStt + nLen > rText.getLength(), "sw.core", "String in ThaiJustify too small" );
+    SAL_WARN_IF( nStt + nLen > TextFrameIndex(rText.getLength()), "sw.core", "String in ThaiJustify too small" );
 
-    SwTwips nNumOfTwipsToDistribute = nSpaceAdd * nNumberOfBlanks /
+    SwTwips nNumOfTwipsToDistribute = nSpaceAdd * sal_Int32(nNumberOfBlanks) /
                                       SPACING_PRECISION_FACTOR;
 
     long nSpaceSum = 0;
-    sal_Int32 nCnt = 0;
+    TextFrameIndex nCnt(0);
 
-    for (sal_Int32 nI = 0; nI < nLen; ++nI)
+    for (sal_Int32 nI = 0; nI < sal_Int32(nLen); ++nI)
     {
-        const sal_Unicode cCh = rText[nStt + nI];
+        const sal_Unicode cCh = rText[sal_Int32(nStt) + nI];
 
         // check if character is not above or below base
         if ( ( 0xE34 > cCh || cCh > 0xE3A ) &&
              ( 0xE47 > cCh || cCh > 0xE4E ) && cCh != 0xE31 )
         {
-            if ( nNumberOfBlanks > 0 )
+            if (nNumberOfBlanks > TextFrameIndex(0))
             {
-                nSpaceAdd = nNumOfTwipsToDistribute / nNumberOfBlanks;
+                nSpaceAdd = nNumOfTwipsToDistribute / sal_Int32(nNumberOfBlanks);
                 --nNumberOfBlanks;
                 nNumOfTwipsToDistribute -= nSpaceAdd;
             }
@@ -2241,16 +2241,17 @@ void SwScriptInfo::CalcHiddenRanges( const SwTextNode& rNode, MultiSelection& rH
 TextFrameIndex SwScriptInfo::CountCJKCharacters(const OUString &rText,
     TextFrameIndex nPos, TextFrameIndex const nEnd, LanguageType aLang)
 {
-    sal_Int32 nCount = 0;
+    TextFrameIndex nCount(0);
     if (nEnd > nPos)
     {
         sal_Int32 nDone = 0;
         const lang::Locale &rLocale = g_pBreakIt->GetLocale( aLang );
         while ( nPos < nEnd )
         {
-            nPos = g_pBreakIt->GetBreakIter()->nextCharacters( rText, nPos,
+            nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->nextCharacters(
+                    rText, sal_Int32(nPos),
                     rLocale,
-                    i18n::CharacterIteratorMode::SKIPCELL, 1, nDone );
+                    i18n::CharacterIteratorMode::SKIPCELL, 1, nDone));
             nCount++;
         }
     }
@@ -2265,21 +2266,21 @@ void SwScriptInfo::CJKJustify( const OUString& rText, long* pKernArray,
                                      TextFrameIndex const nLen, LanguageType aLang,
                                      long nSpaceAdd, bool bIsSpaceStop )
 {
-    assert( pKernArray != nullptr && nStt >= 0 );
-    if (nLen > 0)
+    assert( pKernArray != nullptr && sal_Int32(nStt) >= 0 );
+    if (sal_Int32(nLen) > 0)
     {
         long nSpaceSum = 0;
         const lang::Locale &rLocale = g_pBreakIt->GetLocale( aLang );
         sal_Int32 nDone = 0;
-        sal_Int32 nNext = nStt;
-        for ( sal_Int32 nI = 0; nI < nLen ; ++nI )
+        sal_Int32 nNext(nStt);
+        for ( sal_Int32 nI = 0; nI < sal_Int32(nLen); ++nI )
         {
-            if ( nI + nStt == nNext )
+            if (nI + sal_Int32(nStt) == nNext)
             {
                 nNext = g_pBreakIt->GetBreakIter()->nextCharacters( rText, nNext,
                         rLocale,
                         i18n::CharacterIteratorMode::SKIPCELL, 1, nDone );
-                if (nNext < nStt + nLen || !bIsSpaceStop)
+                if (nNext < sal_Int32(nStt + nLen) || !bIsSpaceStop)
                     nSpaceSum += nSpaceAdd;
             }
             pKernArray[ nI ] += nSpaceSum;
commit 9ba9f9fe137cffd0c65978f2f4684e00a1f780bb
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 24 10:40:07 2018 +0200

    sw_redlinehide: static functions of SwScriptInfo
    
    Some of these are only called with TextFrameIndex, so just convert the
    parameter types to that for simplicity.
    
    Change-Id: I73d418bd42ec95b15548b3df44736de0092ad87d

diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 9a92a06557cf..8ab6e7643598 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -332,7 +332,7 @@ public:
                  Start index of the text
      @return Returns if the language is an Arabic language
  */
-    static bool IsArabicText( const OUString& rText, sal_Int32 nStt, sal_Int32 nLen );
+    static bool IsArabicText(const OUString& rText, TextFrameIndex nStt, TextFrameIndex nLen);
 
 /** Performs a thai justification on the kerning array
 
@@ -352,16 +352,18 @@ public:
                 The value which has to be added to the cells.
     @return The number of extra spaces in the given range
 */
-    static sal_Int32 ThaiJustify( const OUString& rText, long* pKernArray,
-                                  long* pScrArray, sal_Int32 nIdx,
-                                  sal_Int32 nLen, sal_Int32 nNumberOfBlanks = 0,
+    static TextFrameIndex ThaiJustify( const OUString& rText, long* pKernArray,
+                                  long* pScrArray, TextFrameIndex nIdx,
+                                  TextFrameIndex nLen,
+                                  TextFrameIndex nNumberOfBlanks = TextFrameIndex(0),
                                   long nSpaceAdd = 0 );
 
-    static sal_Int32 CountCJKCharacters( const OUString &rText, sal_Int32 nPos, sal_Int32 nEnd, LanguageType aLang);
+    static TextFrameIndex CountCJKCharacters(const OUString &rText,
+            TextFrameIndex nPos, TextFrameIndex nEnd, LanguageType aLang);
 
     static void CJKJustify( const OUString& rText, long* pKernArray,
-                                  long* pScrArray, sal_Int32 nStt,
-                                  sal_Int32 nLen, LanguageType aLang,
+                                  long* pScrArray, TextFrameIndex nStt,
+                                  TextFrameIndex nLen, LanguageType aLang,
                                   long nSpaceAdd, bool bIsSpaceStop );
 
     static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index faa412a44d6c..49cb28187867 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1803,7 +1803,8 @@ sal_Int32 SwScriptInfo::KashidaJustify( long* pKernArray,
 // Checks if the current text is 'Arabic' text. Note that only the first
 // character has to be checked because a ctl portion only contains one
 // script, see NewTextPortion
-bool SwScriptInfo::IsArabicText( const OUString& rText, sal_Int32 nStt, sal_Int32 nLen )
+bool SwScriptInfo::IsArabicText(const OUString& rText,
+        TextFrameIndex const nStt, TextFrameIndex const nLen)
 {
     using namespace ::com::sun::star::i18n;
     static const ScriptTypeList typeList[] = {
@@ -1989,9 +1990,10 @@ void SwScriptInfo::MarkKashidasInvalid(sal_Int32 const nCnt,
     }
 }
 
-sal_Int32 SwScriptInfo::ThaiJustify( const OUString& rText, long* pKernArray,
-                                     long* pScrArray, sal_Int32 nStt,
-                                     sal_Int32 nLen, sal_Int32 nNumberOfBlanks,
+TextFrameIndex SwScriptInfo::ThaiJustify( const OUString& rText, long* pKernArray,
+                                     long* pScrArray, TextFrameIndex const nStt,
+                                     TextFrameIndex const nLen,
+                                     TextFrameIndex nNumberOfBlanks,
                                      long nSpaceAdd )
 {
     SAL_WARN_IF( nStt + nLen > rText.getLength(), "sw.core", "String in ThaiJustify too small" );
@@ -2236,7 +2238,8 @@ void SwScriptInfo::CalcHiddenRanges( const SwTextNode& rNode, MultiSelection& rH
     rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
 }
 
-sal_Int32 SwScriptInfo::CountCJKCharacters( const OUString &rText, sal_Int32 nPos, sal_Int32 nEnd, LanguageType aLang)
+TextFrameIndex SwScriptInfo::CountCJKCharacters(const OUString &rText,
+    TextFrameIndex nPos, TextFrameIndex const nEnd, LanguageType aLang)
 {
     sal_Int32 nCount = 0;
     if (nEnd > nPos)
@@ -2258,8 +2261,8 @@ sal_Int32 SwScriptInfo::CountCJKCharacters( const OUString &rText, sal_Int32 nPo
 }
 
 void SwScriptInfo::CJKJustify( const OUString& rText, long* pKernArray,
-                                     long* pScrArray, sal_Int32 nStt,
-                                     sal_Int32 nLen, LanguageType aLang,
+                                     long* pScrArray, TextFrameIndex const nStt,
+                                     TextFrameIndex const nLen, LanguageType aLang,
                                      long nSpaceAdd, bool bIsSpaceStop )
 {
     assert( pKernArray != nullptr && nStt >= 0 );
commit 9c9c47692b46289e2c47c7420672372b511ed80d
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 23 18:41:15 2018 +0200

    sw_redlinehide: portxt.cxx
    
    Not sure if these space-counting functions should use TextFrameIndex or
    not, but there's quite a lot of them and half already converted...
    
    Change-Id: I27adbd752eada7cfe8b4782a6e183563b4c057f3

diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 81b6aaad6017..703591b7feed 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -49,8 +49,8 @@ using namespace ::com::sun::star::i18n::ScriptType;
 
 // Returns for how many characters an extra space has to be added
 // (for justified alignment).
-static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
-                               const SwLinePortion& rPor )
+static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf,
+        const OUString* pStr, const SwLinePortion& rPor)
 {
     TextFrameIndex nPos, nEnd;
     const SwScriptInfo* pSI = nullptr;
@@ -69,7 +69,7 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
         pSI = &const_cast<SwParaPortion*>(rInf.GetParaPortion())->GetScriptInfo();
     }
 
-    sal_Int32 nCnt = 0;
+    TextFrameIndex nCnt(0);
     sal_uInt8 nScript = 0;
 
     // If portion consists of Asian characters and language is not
@@ -122,7 +122,7 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
             // i60591: need to check result of KashidaJustify
             // determine if kashida justification is applicable
             if (nKashRes != -1)
-                return nKashRes;
+                return TextFrameIndex(nKashRes);
         }
     }
 
@@ -575,7 +575,7 @@ bool SwTextPortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
 TextFrameIndex SwTextPortion::GetSpaceCnt(const SwTextSizeInfo &rInf,
                                           TextFrameIndex& rCharCnt) const
 {
-    sal_Int32 nCnt = 0;
+    TextFrameIndex nCnt(0);
     TextFrameIndex nPos(0);
 
     if ( rInf.SnapToGrid() )
@@ -613,7 +613,7 @@ TextFrameIndex SwTextPortion::GetSpaceCnt(const SwTextSizeInfo &rInf,
 
 long SwTextPortion::CalcSpacing( long nSpaceAdd, const SwTextSizeInfo &rInf ) const
 {
-    sal_Int32 nCnt = 0;
+    TextFrameIndex nCnt(0);
 
     if ( rInf.SnapToGrid() )
     {
@@ -639,7 +639,7 @@ long SwTextPortion::CalcSpacing( long nSpaceAdd, const SwTextSizeInfo &rInf ) co
             else
             {
                 nSpaceAdd = -nSpaceAdd;
-                nCnt = aStr.getLength();
+                nCnt = TextFrameIndex(aStr.getLength());
             }
         }
     }
@@ -665,7 +665,7 @@ long SwTextPortion::CalcSpacing( long nSpaceAdd, const SwTextSizeInfo &rInf ) co
         }
     }
 
-    return nCnt * nSpaceAdd / SPACING_PRECISION_FACTOR;
+    return sal_Int32(nCnt) * nSpaceAdd / SPACING_PRECISION_FACTOR;
 }
 
 void SwTextPortion::HandlePortion( SwPortionHandler& rPH ) const
commit 90554af2d5ec1e4bfeaab2bb0c91f39cea20d3ea
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 23 18:35:01 2018 +0200

    sw_redlinehide: more portxt.cxx
    
    Change-Id: I0400794e30231d98e69569306aeaf9e43a5d5907

diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 1bef7cfafab0..81b6aaad6017 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -52,14 +52,14 @@ using namespace ::com::sun::star::i18n::ScriptType;
 static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
                                const SwLinePortion& rPor )
 {
-    sal_Int32 nPos, nEnd;
+    TextFrameIndex nPos, nEnd;
     const SwScriptInfo* pSI = nullptr;
 
     if ( pStr )
     {
         // passing a string means we are inside a field
-        nPos = 0;
-        nEnd = pStr->getLength();
+        nPos = TextFrameIndex(0);
+        nEnd = TextFrameIndex(pStr->getLength());
     }
     else
     {
@@ -78,7 +78,8 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
     if ( pSI )
         nScript = pSI->ScriptType( nPos );
     else
-        nScript = static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType( *pStr, nPos ));
+        nScript = static_cast<sal_uInt8>(
+            g_pBreakIt->GetBreakIter()->getScriptType(*pStr, sal_Int32(nPos)));
 
     // Note: rInf.GetIdx() can differ from nPos,
     // e.g., when rPor is a field portion. nPos referes to the string passed
@@ -152,18 +153,18 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
     // Note: We do not want to add space to an isolated latin blank in front
     // of some complex characters in RTL environment
     const bool bDoNotAddSpace =
-            LATIN == nScript && ( nEnd == nPos + 1 ) && pSI &&
+            LATIN == nScript && (nEnd == nPos + TextFrameIndex(1)) && pSI &&
             ( i18n::ScriptType::COMPLEX ==
-              pSI->ScriptType( nPos + 1 ) ) &&
+              pSI->ScriptType(nPos + TextFrameIndex(1))) &&
             rInf.GetTextFrame() && rInf.GetTextFrame()->IsRightToLeft();
 
     if ( bDoNotAddSpace )
         return nCnt;
 
-    sal_Int32 nTextEnd = std::min(nEnd, pStr->getLength());
+    TextFrameIndex nTextEnd = std::min(nEnd, TextFrameIndex(pStr->getLength()));
     for ( ; nPos < nTextEnd; ++nPos )
     {
-        if( CH_BLANK == (*pStr)[ nPos ] )
+        if (CH_BLANK == (*pStr)[ sal_Int32(nPos) ])
             ++nCnt;
     }
 
@@ -173,7 +174,7 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
     // nPos referes to the original string, even if a field string has
     // been passed to this function
     nPos = rInf.GetIdx() + rPor.GetLen();
-    if ( nPos < rInf.GetText().getLength() )
+    if (nPos < TextFrameIndex(rInf.GetText().getLength()))
     {
         sal_uInt8 nNextScript = 0;
         const SwLinePortion* pPor = rPor.GetPortion();
@@ -196,7 +197,8 @@ static sal_Int32 lcl_AddSpace( const SwTextSizeInfo &rInf, const OUString* pStr,
             nNextScript = static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType( aStr, 0 ));
         }
         else
-            nNextScript = static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType( rInf.GetText(), nPos ));
+            nNextScript = static_cast<sal_uInt8>(
+                g_pBreakIt->GetBreakIter()->getScriptType(rInf.GetText(), sal_Int32(nPos)));
 
         if( ASIAN == nNextScript )
         {
@@ -574,7 +576,7 @@ TextFrameIndex SwTextPortion::GetSpaceCnt(const SwTextSizeInfo &rInf,
                                           TextFrameIndex& rCharCnt) const
 {
     sal_Int32 nCnt = 0;
-    sal_Int32 nPos = 0;
+    TextFrameIndex nPos(0);
 
     if ( rInf.SnapToGrid() )
     {
@@ -597,7 +599,7 @@ TextFrameIndex SwTextPortion::GetSpaceCnt(const SwTextSizeInfo &rInf,
             const_cast<SwTextSizeInfo &>(rInf).SetOnWin( bOldOnWin );
 
             nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
-            nPos = aStr.getLength();
+            nPos = TextFrameIndex(aStr.getLength());
         }
     }
     else if( !IsDropPortion() )
commit 511904b0b117d7ef5738d18b9c2ef063ea1427b8
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 23 18:01:48 2018 +0200

    sw_redlinehide: convert SwTextFrame::PrepareVisualMove()
    
    Change-Id: Icc9a7f44ad10f0ea556681d832bc3716e9341da7

diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx
index c0ba1765beee..c7c53d83e4f9 100644
--- a/sw/source/core/text/frmcrsr.cxx
+++ b/sw/source/core/text/frmcrsr.cxx
@@ -1075,18 +1075,19 @@ void SwTextFrame::PrepareVisualMove(TextFrameIndex & nPos, sal_uInt8& nCursorLev
 
     // Bidi functions from icu 2.0
 
-    const sal_Unicode* pLineString = GetTextNode()->GetText().getStr();
+    const sal_Unicode* pLineString = GetText().getStr();
 
     UErrorCode nError = U_ZERO_ERROR;
-    UBiDi* pBidi = ubidi_openSized( nLen, 0, &nError );
-    ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), nLen, nDefaultDir, nullptr, &nError );
+    UBiDi* pBidi = ubidi_openSized( sal_Int32(nLen), 0, &nError );
+    ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString),
+                    sal_Int32(nLen), nDefaultDir, nullptr, &nError );
 
-    sal_Int32 nTmpPos = 0;
+    TextFrameIndex nTmpPos(0);
     bool bOutOfBounds = false;
 
     if ( nPos < nStt + nLen )
     {
-        nTmpPos = ubidi_getVisualIndex( pBidi, nPos, &nError );
+        nTmpPos = TextFrameIndex(ubidi_getVisualIndex( pBidi, sal_Int32(nPos), &nError ));
 
         // visual indices are always LTR aligned
         if ( bVisualRight )
@@ -1117,7 +1118,7 @@ void SwTextFrame::PrepareVisualMove(TextFrameIndex & nPos, sal_uInt8& nCursorLev
 
     if ( ! bOutOfBounds )
     {
-        nPos = ubidi_getLogicalIndex( pBidi, nTmpPos, &nError );
+        nPos = TextFrameIndex(ubidi_getLogicalIndex( pBidi, sal_Int32(nTmpPos), &nError ));
 
         if ( bForward )
         {
commit 36b2489d6cdb8f44fa11f04b028b7f0736aa541a
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 23 17:33:20 2018 +0200

    sw_redlinehide: split up SwScriptInfo::WhichFont confusion
    
    Change-Id: Ic300ddc7fba4294317096c17b9b907b8b794b646

diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 0100a1b4cefd..9a92a06557cf 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -367,7 +367,8 @@ public:
     static SwScriptInfo* GetScriptInfo( const SwTextNode& rNode,
                                         bool bAllowInvalid = false );
 
-    static SwFontScript WhichFont(sal_Int32 nIdx, const OUString* pText, const SwScriptInfo* pSI);
+    SwFontScript WhichFont(TextFrameIndex nIdx) const;
+    static SwFontScript WhichFont(sal_Int32 nIdx, OUString const & rText);
 };
 
 #endif
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index 3a7de75f3067..217615337e37 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -190,7 +190,7 @@ void SwExtraPainter::PaintExtra( SwTwips nY, long nAsc, long nMax, bool bRed )
                                 : rLineInf.GetDivider() );
 
     // Get script type of line numbering:
-    pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmp, nullptr ) );
+    pFnt->SetActual( SwScriptInfo::WhichFont(0, aTmp) );
 
     SwDrawTextInfo aDrawInf( pSh, *pSh->GetOut(), aTmp, 0, aTmp.getLength() );
     aDrawInf.SetSpace( 0 );
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 7b12392321a4..e3173840d91b 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -374,7 +374,7 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
         }
     }
 
-    m_pFont->SetActual( SwScriptInfo::WhichFont( nNewPos, nullptr, m_pScriptInfo ) );
+    m_pFont->SetActual( m_pScriptInfo->WhichFont(nNewPos) );
 
     if( m_pRedline )
         m_nChgCnt = m_nChgCnt + m_pRedline->Seek(*m_pFont, newPos.first->GetIndex(), newPos.second, m_nPosition);
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 636121362f0a..186261fda6ff 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -100,7 +100,7 @@ static void lcl_GetCharRectInsideField( SwTextSizeInfo& rInf, SwRect& rOrig,
         if ( pString )
         {
             // get script for field portion
-            rInf.GetFont()->SetActual( SwScriptInfo::WhichFont( 0, pString, nullptr ) );
+            rInf.GetFont()->SetActual( SwScriptInfo::WhichFont(0, *pString) );
 
             TextFrameIndex const nOldLen = pPor->GetLen();
             const_cast<SwLinePortion*>(pPor)->SetLen(TextFrameIndex(nLen - 1));
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 86e59b0effdf..4b3455c79dbe 100755
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -638,7 +638,7 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
             const SwFontScript nCurrScript = m_pFont->GetActual(); // pScriptInfo->ScriptType( rInf.GetIdx() );
             const SwFontScript nNextScript = nTmp >= rInf.GetText().getLength() ?
                                      SwFontScript::CJK :
-                                     SwScriptInfo::WhichFont( nTmp, nullptr, m_pScriptInfo );
+                                     m_pScriptInfo->WhichFont(nTmp);
 
             // snap non-asian text to grid if next portion is ASIAN or
             // there are no more portions in this line
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index ffa510b1a570..faa412a44d6c 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -680,13 +680,8 @@ SwScriptInfo::~SwScriptInfo()
 
 // Converts i18n Script Type (LATIN, ASIAN, COMPLEX, WEAK) to
 // Sw Script Types (SwFontScript::Latin, SwFontScript::CJK, SwFontScript::CTL), used to identify the font
-SwFontScript SwScriptInfo::WhichFont( sal_Int32 nIdx, const OUString* pText, const SwScriptInfo* pSI )
+static SwFontScript lcl_ScriptToFont(sal_uInt16 const nScript)
 {
-    assert((pSI || pText) && "How should I determine the script type?");
-    const sal_uInt16 nScript = pSI
-        ? pSI->ScriptType( nIdx )                         // use our SwScriptInfo if available
-        : g_pBreakIt->GetRealScriptOfText( *pText, nIdx ); // else  ask the break iterator
-
     switch ( nScript ) {
         case i18n::ScriptType::LATIN : return SwFontScript::Latin;
         case i18n::ScriptType::ASIAN : return SwFontScript::CJK;
@@ -697,6 +692,18 @@ SwFontScript SwScriptInfo::WhichFont( sal_Int32 nIdx, const OUString* pText, con
     return SwFontScript::Latin;
 }
 
+SwFontScript SwScriptInfo::WhichFont(TextFrameIndex const nIdx) const
+{
+    const sal_uInt16 nScript(ScriptType(nIdx));
+    return lcl_ScriptToFont(nScript);
+}
+
+SwFontScript SwScriptInfo::WhichFont(sal_Int32 nIdx, OUString const& rText)
+{
+    const sal_uInt16 nScript(g_pBreakIt->GetRealScriptOfText(rText, nIdx));
+    return lcl_ScriptToFont(nScript);
+}
+
 // searches for script changes in rText and stores them
 void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
         sw::MergedPara const*const pMerged)
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 2e4cbf836ccd..0af3e2368d0a 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -309,14 +309,14 @@ SwDoubleLinePortion::SwDoubleLinePortion(
     if( pBracket->cPre > 255 )
     {
         OUString aText = OUString(pBracket->cPre);
-        nTmp = SwScriptInfo::WhichFont( 0, &aText, nullptr );
+        nTmp = SwScriptInfo::WhichFont(0, aText);
     }
     pBracket->nPreScript = nTmp;
     nTmp = SW_SCRIPTS;
     if( pBracket->cPost > 255 )
     {
         OUString aText = OUString(pBracket->cPost);
-        nTmp = SwScriptInfo::WhichFont( 0, &aText, nullptr );
+        nTmp = SwScriptInfo::WhichFont(0, aText);
     }
     pBracket->nPostScript = nTmp;
 
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 53184f198824..3d8225c79049 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -150,9 +150,9 @@ void SwAttrIter::InitFontAndAttrHandler(SwTextNode const& rTextNode,
 
     assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
 
-    m_pFont->SetActual( SwScriptInfo::WhichFont( 0, nullptr, m_pScriptInfo ) );
+    m_pFont->SetActual( m_pScriptInfo->WhichFont(TextFrameIndex(0)) );
 
-    sal_Int32 nChg = 0;
+    TextFrameIndex nChg(0);
     size_t nCnt = 0;
 
     do
@@ -177,7 +177,7 @@ void SwAttrIter::InitFontAndAttrHandler(SwTextNode const& rTextNode,
             m_pFont->GetMagic( m_aMagicNo[ nTmp ], m_aFontIdx[ nTmp ], nTmp );
         }
     }
-    while (nChg < rText.getLength());
+    while (nChg < TextFrameIndex(rText.getLength()));
 }
 
 void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode,
diff --git a/sw/source/core/text/txtftn.cxx b/sw/source/core/text/txtftn.cxx
index 6dba5849218b..bd9cf48c0967 100644
--- a/sw/source/core/text/txtftn.cxx
+++ b/sw/source/core/text/txtftn.cxx
@@ -1251,7 +1251,7 @@ SwFootnoteSave::SwFootnoteSave( const SwTextSizeInfo &rInf,
         {
             // examine text and set script
             OUString aTmpStr( rFootnote.GetViewNumStr( *pDoc ) );
-            pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmpStr, nullptr ) );
+            pFnt->SetActual( SwScriptInfo::WhichFont(0, aTmpStr) );
         }
 
         const SwEndNoteInfo* pInfo;
commit 71a45af3245007bc79d7b58bb286941630167928
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 23 16:19:21 2018 +0200

    sw_redlinehide: trivial conversions in SwScriptInfo
    
    Change-Id: Idab0b0a351c5f1ee176f9a2c8f1d3780e21ecf26

diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index fa27754cf245..ffa510b1a570 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -730,10 +730,10 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
 
     // SCRIPT AND SCRIPT RELATED INFORMATION
 
-    sal_Int32 nChg = m_nInvalidityPos;
+    TextFrameIndex nChg = m_nInvalidityPos;
 
     // COMPLETE_STRING means the data structure is up to date
-    m_nInvalidityPos = COMPLETE_STRING;
+    m_nInvalidityPos = TextFrameIndex(COMPLETE_STRING);
 
     // this is the default direction
     m_nDefaultDir = static_cast<sal_uInt8>(bRTL ? UBIDI_RTL : UBIDI_LTR);
@@ -799,18 +799,18 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
     if ( nChg )
         --nChg;
 
-    const sal_Int32 nGrpStart = nCnt ? GetScriptChg( nCnt - 1 ) : 0;
+    const TextFrameIndex nGrpStart = nCnt ? GetScriptChg(nCnt - 1) : TextFrameIndex(0);
 
     // we go back in our group until we reach the first character of
     // type nScript
     while ( nChg > nGrpStart &&
-            nScript != g_pBreakIt->GetBreakIter()->getScriptType( rText, nChg ) )
+            nScript != g_pBreakIt->GetBreakIter()->getScriptType(rText, sal_Int32(nChg)))
         --nChg;
 
     // If we are at the start of a group, we do not trust nScript,
     // we better get nScript from the breakiterator:
     if ( nChg == nGrpStart )
-        nScript = static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType( rText, nChg ));
+        nScript = static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType(rText, sal_Int32(nChg)));
 
     // INVALID DATA FROM THE SCRIPT INFO ARRAYS HAS TO BE DELETED:
 
@@ -818,7 +818,7 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
     m_ScriptChanges.erase(m_ScriptChanges.begin() + nCnt, m_ScriptChanges.end());
 
     // get the start of the last compression group
-    sal_Int32 nLastCompression = nChg;
+    TextFrameIndex nLastCompression = nChg;
     if( nCntComp )
     {
         --nCntComp;
@@ -835,7 +835,7 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
             m_CompressionChanges.end());
 
     // get the start of the last kashida group
-    sal_Int32 nLastKashida = nChg;
+    TextFrameIndex nLastKashida = nChg;
     if( nCntKash && i18n::ScriptType::COMPLEX == nScript )
     {
         --nCntKash;
@@ -848,17 +848,17 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
     // TAKE CARE OF WEAK CHARACTERS: WE MUST FIND AN APPROPRIATE
     // SCRIPT FOR WEAK CHARACTERS AT THE BEGINNING OF A PARAGRAPH
 
-    if( WEAK == g_pBreakIt->GetBreakIter()->getScriptType( rText, nChg ) )
+    if (WEAK == g_pBreakIt->GetBreakIter()->getScriptType(rText, sal_Int32(nChg)))
     {
         // If the beginning of the current group is weak, this means that
         // all of the characters in this group are weak. We have to assign
         // the scripts to these characters depending on the fonts which are
         // set for these characters to display them.
-        sal_Int32 nEnd =
-                g_pBreakIt->GetBreakIter()->endOfScript( rText, nChg, WEAK );
+        TextFrameIndex nEnd = TextFrameIndex(
+            g_pBreakIt->GetBreakIter()->endOfScript(rText, sal_Int32(nChg), WEAK));
 
-        if (nEnd > rText.getLength() || nEnd < 0)
-            nEnd = rText.getLength();
+        if (nEnd > TextFrameIndex(rText.getLength()) || nEnd < TextFrameIndex(0))
+            nEnd = TextFrameIndex(rText.getLength());
 
         nScript = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() );
 
@@ -869,9 +869,9 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
         nChg = nEnd;
 
         // Get next script type or set to weak in order to exit
-        sal_uInt8 nNextScript = ( nEnd < rText.getLength() ) ?
-           static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType( rText, nEnd )) :
-           sal_uInt8(WEAK);
+        sal_uInt8 nNextScript = (nEnd < TextFrameIndex(rText.getLength()))
+            ? static_cast<sal_uInt8>(g_pBreakIt->GetBreakIter()->getScriptType(rText, sal_Int32(nEnd)))
+            : sal_uInt8(WEAK);
 
         if ( nScript != nNextScript )
         {
@@ -883,45 +883,53 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
 
     // UPDATE THE SCRIPT INFO ARRAYS:
 
-    while (nChg < rText.getLength() || (m_ScriptChanges.empty() && rText.isEmpty()))
+    while (nChg < TextFrameIndex(rText.getLength())
+           || (m_ScriptChanges.empty() && rText.isEmpty()))
     {
         SAL_WARN_IF( i18n::ScriptType::WEAK == nScript,
                 "sw.core", "Inserting WEAK into SwScriptInfo structure" );
 
-        sal_Int32 nSearchStt = nChg;
-        nChg = g_pBreakIt->GetBreakIter()->endOfScript( rText, nSearchStt, nScript );
+        TextFrameIndex nSearchStt = nChg;
+        nChg = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfScript(
+                    rText, sal_Int32(nSearchStt), nScript));
 
-        if (nChg > rText.getLength() || nChg < 0)
-            nChg = rText.getLength();
+        if (nChg > TextFrameIndex(rText.getLength()) || nChg < TextFrameIndex(0))
+            nChg = TextFrameIndex(rText.getLength());
 
         // #i28203#
         // for 'complex' portions, we make sure that a portion does not contain more
         // than one script:
         if( i18n::ScriptType::COMPLEX == nScript )
         {
-            const short nScriptType = ScriptTypeDetector::getCTLScriptType( rText, nSearchStt );
-            sal_Int32 nNextCTLScriptStart = nSearchStt;
+            const short nScriptType = ScriptTypeDetector::getCTLScriptType(
+                    rText, sal_Int32(nSearchStt) );
+            TextFrameIndex nNextCTLScriptStart = nSearchStt;
             short nCurrentScriptType = nScriptType;
             while( css::i18n::CTLScriptType::CTL_UNKNOWN == nCurrentScriptType || nScriptType == nCurrentScriptType )
             {
-                nNextCTLScriptStart = ScriptTypeDetector::endOfCTLScriptType( rText, nNextCTLScriptStart );
-                if( nNextCTLScriptStart >= rText.getLength() || nNextCTLScriptStart >= nChg )
+                nNextCTLScriptStart = TextFrameIndex(
+                        ScriptTypeDetector::endOfCTLScriptType(
+                            rText, sal_Int32(nNextCTLScriptStart)));
+                if (nNextCTLScriptStart >= TextFrameIndex(rText.getLength())
+                    || nNextCTLScriptStart >= nChg)
                     break;
-                nCurrentScriptType = ScriptTypeDetector::getCTLScriptType( rText, nNextCTLScriptStart );
+                nCurrentScriptType = ScriptTypeDetector::getCTLScriptType(
+                                        rText, sal_Int32(nNextCTLScriptStart));
             }
             nChg = std::min( nChg, nNextCTLScriptStart );
         }
 
         // special case for dotted circle since it can be used with complex
         // before a mark, so we want it associated with the mark's script
-        if (nChg < rText.getLength() && nChg > 0 && (i18n::ScriptType::WEAK ==
-            g_pBreakIt->GetBreakIter()->getScriptType(rText,nChg - 1)))
+        if (nChg < TextFrameIndex(rText.getLength()) && nChg > TextFrameIndex(0)
+            && (i18n::ScriptType::WEAK ==
+                g_pBreakIt->GetBreakIter()->getScriptType(rText, sal_Int32(nChg) - 1)))
         {
-            int8_t nType = u_charType(rText[nChg] );
+            int8_t nType = u_charType(rText[sal_Int32(nChg)]);
             if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
                 nType == U_COMBINING_SPACING_MARK )
             {
-                m_ScriptChanges.emplace_back(nChg-1, nScript);
+                m_ScriptChanges.emplace_back(nChg-TextFrameIndex(1), nScript);
             }
             else
             {
@@ -941,11 +949,11 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
         {
             CompType ePrevState = NONE;
             CompType eState = NONE;
-            sal_Int32 nPrevChg = nLastCompression;
+            TextFrameIndex nPrevChg = nLastCompression;
 
             while ( nLastCompression < nChg )
             {
-                sal_Unicode cChar = rText[ nLastCompression ];
+                sal_Unicode cChar = rText[ sal_Int32(nLastCompression) ];
 
                 // examine current character
                 switch ( cChar )
@@ -1168,8 +1176,8 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& rNode,
             } // end of kashida search
         }
 
-        if ( nChg < rText.getLength() )

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list