[Libreoffice-commits] .: 2 commits - sw/source

Michael Stahl mst at kemper.freedesktop.org
Mon Jun 4 13:00:50 PDT 2012


 sw/source/ui/docvw/edtwin.cxx  |  210 ++++++++++++++++++++++++++---------------
 sw/source/ui/inc/gloslst.hxx   |    5 
 sw/source/ui/utlui/gloslst.cxx |    6 -
 3 files changed, 141 insertions(+), 80 deletions(-)

New commits:
commit 230662c3afa208780d280401d63add3eece7ab8f
Author: Brad Sowden <code at sowden.org>
Date:   Mon Jun 4 22:02:34 2012 +1200

    Smarter auto-complete capitalization (#i22961#) and i18n handling
    
    If a word is in sentence case then the auto-completed word should
    be in the same case i.e. if the auto-complete list contains the
    word "LIBRE" then "Lib" should auto-complete to "Libre" rather
    than "LibRE". See OpenOffice bug 22961.
    
    Also implement better i18n handling for calander month and day
    names. Previously, if a month or day name was not ASCII then it
    would only auto-complete if it exactly matched the names retrieved
    from the internal calander i.e. had be a case sensitive match.
    
    Change-Id: I0c4543bd9e912072bce1ceaf4adecd41b55b576b

diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx
index dca8219..831ab46 100644
--- a/sw/source/ui/docvw/edtwin.cxx
+++ b/sw/source/ui/docvw/edtwin.cxx
@@ -5565,67 +5565,93 @@ void QuickHelpData::Stop( SwWrtShell& rSh )
 
 void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord )
 {
+    enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER };
+
+    // Determine word capitalization
+    const CharClass& rCC = GetAppCharClass();
+    const String sWordLower = rCC.lowercase( rWord );
+    Capitalization aWordCase = CASE_OTHER;
+    if ( rWord.Len() > 0 )
+    {
+        if ( rWord.GetChar(0) == sWordLower.GetChar(0) )
+        {
+            if ( rWord == sWordLower )
+                aWordCase = CASE_LOWER;
+        }
+        else
+        {
+            // First character is not lower case i.e. assume upper or title case
+            String sWordSentence = sWordLower;
+            sWordSentence.SetChar( 0, rWord.GetChar(0) );
+            if ( rWord == sWordSentence )
+                aWordCase = CASE_SENTENCE;
+            else
+            {
+                if ( rWord == static_cast<String>( rCC.uppercase( rWord ) ) )
+                    aWordCase = CASE_UPPER;
+            }
+        }
+    }
+
     salhelper::SingletonRef<SwCalendarWrapper>* pCalendar = s_getCalendarWrapper();
     (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() );
 
+    // Add matching calendar month and day names
+    uno::Sequence< i18n::CalendarItem2 > aNames( (*pCalendar)->getMonths() );
+    for ( sal_uInt16 i = 0; i < 2; ++i )
     {
-        uno::Sequence< i18n::CalendarItem2 > aNames(
-                                            (*pCalendar)->getMonths() );
-        for( int n = 0; n < 2; ++n )
+        for ( long n = 0; n < aNames.getLength(); ++n )
         {
-            for( long nPos = 0, nEnd = aNames.getLength(); nPos < nEnd; ++nPos )
+            const String& rStr( aNames[n].FullName );
+            // Check string longer than word and case insensitive match
+            if( rStr.Len() > rWord.Len() &&
+                static_cast<String>( rCC.lowercase( rStr, 0, rWord.Len() ) )
+                == sWordLower )
             {
-                String sStr( aNames[ nPos ].FullName );
-                if( rWord.Len() + 1 < sStr.Len() &&
-
-//!!! UNICODE: missing interface
-                    COMPARE_EQUAL == rWord.CompareIgnoreCaseToAscii(
-                                        sStr, rWord.Len() ))
+                if ( aWordCase == CASE_LOWER )
+                    pHelpStrings->push_back( rCC.lowercase( rStr ) );
+                else if ( aWordCase == CASE_SENTENCE )
                 {
-                    pHelpStrings->push_back( sStr );
+                    String sTmp = rCC.lowercase( rStr );
+                    sTmp.SetChar( 0, rStr.GetChar(0) );
+                    pHelpStrings->push_back( sTmp );
                 }
+                else if ( aWordCase == CASE_UPPER )
+                    pHelpStrings->push_back( rCC.uppercase( rStr ) );
+                else // CASE_OTHER - use retrieved capitalization
+                    pHelpStrings->push_back( rStr );
             }
-            if( !n )                    // get data for the second loop
-                aNames = (*pCalendar)->getDays();
         }
+        // Data for second loop iteration
+        if ( i == 0 )
+            aNames = (*pCalendar)->getDays();
     }
 
-    // and than add all words from the AutoCompleteWord-List
-    const SwAutoCompleteWord& rACLst = rSh.GetAutoCompleteWords();
-    sal_uInt16 nStt, nEnd;
-    if( rACLst.GetRange( rWord, nStt, nEnd ) )
+    // Add matching words from AutoCompleteWord list
+    const SwAutoCompleteWord& rACList = rSh.GetAutoCompleteWords();
+    sal_uInt16 nPos, nEnd;
+    // TODO - GetRange only performs a case insensitive match for ASCII
+    if ( rACList.GetRange( rWord, nPos, nEnd ) )
     {
-        while( nStt < nEnd )
+        for ( ; nPos < nEnd; ++nPos )
         {
-            const String& rS = rACLst[ nStt ];
-            // only if the count of chars
-            // from the suggest greater as the
-            // actual word
-            if( rS.Len() > rWord.Len() )
+            const String& rStr = rACList[nPos];
+            // Check string longer than word
+            if ( rStr.Len() > rWord.Len() )
             {
-                CharClass &rCC = GetAppCharClass();
-                String aMatch;
-                int upper = 0, lower = 0, letters = 0;
-                for( xub_StrLen i = 0; i < rWord.Len(); i++ ) {
-                    sal_Int32 nCharType = rCC.getCharacterType( rWord, i );
-                    if( !CharClass::isLetterType( nCharType ) )
-                        continue;
-                    letters++;
-                    if( i18n::KCharacterType::LOWER & nCharType )
-                        lower++;
-                    if( i18n::KCharacterType::UPPER & nCharType )
-                        upper++;
+                if ( aWordCase == CASE_LOWER )
+                    pHelpStrings->push_back( rCC.lowercase( rStr ) );
+                else if ( aWordCase == CASE_SENTENCE )
+                {
+                    String sTmp = rCC.lowercase( rStr );
+                    sTmp.SetChar( 0, rStr.GetChar(0) );
+                    pHelpStrings->push_back( sTmp );
                 }
-                if (lower == letters)
-                    aMatch = rCC.lowercase( rS );
-                else if (upper == letters)
-                    aMatch = rCC.uppercase( rS );
-                else // mixed case - use what we have
-                    aMatch = rS;
-
-                pHelpStrings->push_back( aMatch );
+                else if ( aWordCase == CASE_UPPER )
+                    pHelpStrings->push_back( rCC.uppercase( rStr ) );
+                else // CASE_OTHER - use retrieved capitalization
+                    pHelpStrings->push_back( rStr );
             }
-            ++nStt;
         }
     }
 }
commit d7a6815fbf56fd3f8e6712f1c2cb761e8e1bbd8f
Author: Brad Sowden <code at sowden.org>
Date:   Sat Jun 2 19:09:43 2012 +1200

    Replace SvStringsISortDtor in edtwin.cxx and gloslst.[ch]xx
    
    Note that the replacement vector stores all strings first and then
    sort and "unique" are applied (ASCII treated as case-insensitive).
    Previously strings were inserted sequentially and only the first
    version of a string would be stored (case-insensitive ASCII
    comparision). This should have no material impact as the strings
    retreived from SwAutoCompleteWord are already unique (case-
    insensitive ASCII comparison) and the capitalization of the string
    is generally changed anyway to match the capitalization of the word
    to be auto-completed. Also, there appears to be no logical reason
    to store the first inserted version of a string over of the first
    version post-sort.
    
    Change-Id: I132865bbb9b382d417fb2cff9de351fdb2cbfb13

diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx
index 6d5cc4f..dca8219 100644
--- a/sw/source/ui/docvw/edtwin.cxx
+++ b/sw/source/ui/docvw/edtwin.cxx
@@ -143,6 +143,7 @@
 #include <PostItMgr.hxx>
 
 #include <algorithm>
+#include <vector>
 
 #include "../../core/inc/rootfrm.hxx"
 
@@ -271,33 +272,39 @@ public:
 
 struct QuickHelpData
 {
-    SvStringsISortDtor aArr;
+    std::vector<String> *pHelpStrings;
     sal_uInt16* pAttrs;
     CommandExtTextInputData* pCETID;
     sal_uLong nTipId;
     sal_uInt16 nLen, nCurArrPos;
     sal_Bool bClear : 1, bChkInsBlank : 1, bIsTip : 1, bIsAutoText : 1;
 
-    QuickHelpData() : pAttrs( 0 ), pCETID( 0 )  { ClearCntnt(); }
+    QuickHelpData() : pAttrs( 0 ), pCETID( 0 )
+    {
+        pHelpStrings = new std::vector<String>;
+        ClearCntnt();
+    }
+    ~QuickHelpData() { delete pHelpStrings; }
 
     void Move( QuickHelpData& rCpy );
     void ClearCntnt();
     void Start( SwWrtShell& rSh, sal_uInt16 nWrdLen );
     void Stop( SwWrtShell& rSh );
 
-    sal_Bool HasCntnt() const       { return aArr.Count() && 0 != nLen; }
+    sal_Bool HasCntnt() const { return !pHelpStrings->empty() && 0 != nLen; }
 
     void Inc( sal_Bool bEndLess )
-        {
-            if( ++nCurArrPos >= aArr.Count() )
-                nCurArrPos = (bEndLess && !bIsAutoText )? 0 : nCurArrPos-1;
-        }
+    {
+        if( ++nCurArrPos >= pHelpStrings->size() )
+            nCurArrPos = (bEndLess && !bIsAutoText ) ? 0 : nCurArrPos-1;
+    }
     void Dec( sal_Bool bEndLess )
-        {
-            if( 0 == nCurArrPos-- )
-                nCurArrPos = (bEndLess && !bIsAutoText ) ? aArr.Count()-1 : 0;
-        }
+    {
+        if( 0 == nCurArrPos-- )
+            nCurArrPos = (bEndLess && !bIsAutoText ) ?  pHelpStrings->size()-1 : 0;
+    }
     void FillStrArr( SwWrtShell& rSh, const String& rWord );
+    void SortAndFilter();
 };
 
 /*--------------------------------------------------------------------
@@ -2468,7 +2475,7 @@ KEYINPUT_CHECKTABLE_INSDEL:
                 // replace the word or abbreviation with the auto text
                 rSh.StartUndo( UNDO_START );
 
-                String sFnd( *aTmpQHD.aArr[ aTmpQHD.nCurArrPos ] );
+                String sFnd( (*aTmpQHD.pHelpStrings)[ aTmpQHD.nCurArrPos ] );
                 if( aTmpQHD.bIsAutoText )
                 {
                     SwGlossaryList* pList = ::GetGlossaryList();
@@ -5464,9 +5471,9 @@ uno::Reference< ::com::sun::star::accessibility::XAccessible > SwEditWin::Create
 
 void QuickHelpData::Move( QuickHelpData& rCpy )
 {
-    // move pointer
-    aArr.Insert( &rCpy.aArr );
-    rCpy.aArr.Remove( (sal_uInt16)0, rCpy.aArr.Count() );
+    pHelpStrings->clear();
+    std::swap( pHelpStrings, rCpy.pHelpStrings );
+
     bClear = rCpy.bClear;
     nLen = rCpy.nLen;
     nCurArrPos = rCpy.nCurArrPos;
@@ -5478,8 +5485,7 @@ void QuickHelpData::Move( QuickHelpData& rCpy )
     pCETID = rCpy.pCETID;
     rCpy.pCETID = 0;
 
-    if( pAttrs )
-        delete[] pAttrs;
+    delete[] pAttrs;
     pAttrs = rCpy.pAttrs;
     rCpy.pAttrs = 0;
 }
@@ -5489,7 +5495,7 @@ void QuickHelpData::ClearCntnt()
     nLen = nCurArrPos = 0;
     bClear = bChkInsBlank = sal_False;
     nTipId = 0;
-    aArr.DeleteAndDestroy( 0 , aArr.Count() );
+    pHelpStrings->clear();
     bIsTip = sal_True;
     bIsAutoText = sal_True;
     delete pCETID, pCETID = 0;
@@ -5498,8 +5504,11 @@ void QuickHelpData::ClearCntnt()
 
 void QuickHelpData::Start( SwWrtShell& rSh, sal_uInt16 nWrdLen )
 {
-    if( pCETID ) delete pCETID, pCETID = 0;
-    if( pAttrs ) delete[] pAttrs, pAttrs = 0;
+    delete pCETID;
+    pCETID = 0;
+
+    delete[] pAttrs;
+    pAttrs = 0;
 
     if( USHRT_MAX != nWrdLen )
     {
@@ -5515,12 +5524,12 @@ void QuickHelpData::Start( SwWrtShell& rSh, sal_uInt16 nWrdLen )
                     rSh.GetCharRect().Pos() )));
         aPt.Y() -= 3;
         nTipId = Help::ShowTip( &rWin, Rectangle( aPt, Size( 1, 1 )),
-                        *aArr[ nCurArrPos ],
+                        (*pHelpStrings)[ nCurArrPos ],
                         QUICKHELP_LEFT | QUICKHELP_BOTTOM );
     }
     else
     {
-        String sStr( *aArr[ nCurArrPos ] );
+        String sStr( (*pHelpStrings)[ nCurArrPos ] );
         sStr.Erase( 0, nLen );
         sal_uInt16 nL = sStr.Len();
         pAttrs = new sal_uInt16[ nL ];
@@ -5573,9 +5582,7 @@ void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord )
                     COMPARE_EQUAL == rWord.CompareIgnoreCaseToAscii(
                                         sStr, rWord.Len() ))
                 {
-                    String* pNew = new String( sStr );
-                    if( !aArr.Insert( pNew ) )
-                        delete pNew;
+                    pHelpStrings->push_back( sStr );
                 }
             }
             if( !n )                    // get data for the second loop
@@ -5616,15 +5623,42 @@ void QuickHelpData::FillStrArr( SwWrtShell& rSh, const String& rWord )
                 else // mixed case - use what we have
                     aMatch = rS;
 
-                String *pNew = new String( aMatch );
-                if (!aArr.Insert( pNew ))
-                    delete pNew;
+                pHelpStrings->push_back( aMatch );
             }
             ++nStt;
         }
     }
 }
 
+// TODO - implement an i18n aware sort
+void QuickHelpData::SortAndFilter()
+{
+    struct CompareIgnoreCaseAscii
+    {
+        bool operator()(const String& s1, const String& s2) const
+        {
+            return s1.CompareIgnoreCaseToAscii(s2) == COMPARE_LESS;
+        }
+    };
+    std::sort( pHelpStrings->begin(),
+               pHelpStrings->end(),
+               CompareIgnoreCaseAscii() );
+
+    struct EqualIgnoreCaseAscii
+    {
+        bool operator()(const String& s1, const String& s2) const
+        {
+            return s1.CompareIgnoreCaseToAscii(s2) == COMPARE_EQUAL;
+        }
+    };
+    std::vector<String>::iterator it = std::unique( pHelpStrings->begin(),
+                                                    pHelpStrings->end(),
+                                                    EqualIgnoreCaseAscii() );
+    pHelpStrings->erase( it, pHelpStrings->end() );
+
+    nCurArrPos = 0;
+}
+
 void SwEditWin::ShowAutoTextCorrectQuickHelp(
         const String& rWord, SvxAutoCorrCfg* pACfg, SvxAutoCorrect* pACorr,
         sal_Bool bFromIME )
@@ -5634,10 +5668,10 @@ void SwEditWin::ShowAutoTextCorrectQuickHelp(
     if( pACfg->IsAutoTextTip() )
     {
         SwGlossaryList* pList = ::GetGlossaryList();
-        pList->HasLongName( rWord, &pQuickHlpData->aArr );
+        pList->HasLongName( rWord, pQuickHlpData->pHelpStrings );
     }
 
-    if( pQuickHlpData->aArr.Count() )
+    if( !pQuickHlpData->pHelpStrings->empty() )
     {
         pQuickHlpData->bIsTip = sal_True;
         pQuickHlpData->bIsAutoText = sal_True;
@@ -5652,8 +5686,12 @@ void SwEditWin::ShowAutoTextCorrectQuickHelp(
         pQuickHlpData->FillStrArr( rSh, rWord );
     }
 
-    if( pQuickHlpData->aArr.Count() )
+
+    if( !pQuickHlpData->pHelpStrings->empty() )
+    {
+        pQuickHlpData->SortAndFilter();
         pQuickHlpData->Start( rSh, rWord.Len() );
+    }
 }
 
 void SwEditWin::ShowHeaderFooterSeparator( bool bShowHeader, bool bShowFooter )
diff --git a/sw/source/ui/inc/gloslst.hxx b/sw/source/ui/inc/gloslst.hxx
index 66ed6d7..f10cb7b 100644
--- a/sw/source/ui/inc/gloslst.hxx
+++ b/sw/source/ui/inc/gloslst.hxx
@@ -33,10 +33,9 @@
 #include <tools/datetime.hxx>
 #include <tools/string.hxx>
 #include <vcl/timer.hxx>
-#include <svl/svarray.hxx>
 
 class SwGlossaries;
-class SvStringsISortDtor;
+class vector;
 
 struct AutoTextGroup
 {
@@ -66,7 +65,7 @@ public:
         SwGlossaryList();
         ~SwGlossaryList();
 
-    sal_Bool            HasLongName(const String& rBegin, SvStringsISortDtor* pLongNames );
+    bool HasLongName(const String& rBegin, std::vector<String> *pLongNames);
     sal_Bool            GetShortName(const String& rLongName,
                                         String& rShortName, String& rGroupName );
 
diff --git a/sw/source/ui/utlui/gloslst.cxx b/sw/source/ui/utlui/gloslst.cxx
index f5be64a..9203000 100644
--- a/sw/source/ui/utlui/gloslst.cxx
+++ b/sw/source/ui/utlui/gloslst.cxx
@@ -26,7 +26,6 @@
  *
  ************************************************************************/
 
-#include <svl/svstdarr.hxx>
 #include <tools/urlobj.hxx>
 #include <vcl/dialog.hxx>
 #include <vcl/msgbox.hxx>
@@ -423,7 +422,7 @@ void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries)
     passendem Anfang zurueckgeben
 ********************************************************************/
 
-sal_Bool SwGlossaryList::HasLongName(const String& rBegin, SvStringsISortDtor* pLongNames )
+bool SwGlossaryList::HasLongName(const String& rBegin, std::vector<String> *pLongNames)
 {
     if(!bFilled)
         Update();
@@ -441,8 +440,7 @@ sal_Bool SwGlossaryList::HasLongName(const String& rBegin, SvStringsISortDtor* p
             if( rSCmp.isEqual( sBlock.Copy(0, nBeginLen), rBegin ) &&
                 nBeginLen + 1 < sBlock.Len())
             {
-                String* pBlock = new String(sBlock);
-                pLongNames->Insert(pBlock);
+                pLongNames->push_back( sBlock );
                 nFound++;
                 if(FIND_MAX_GLOS == nFound)
                     break;


More information about the Libreoffice-commits mailing list