Hi,
This patch implements the following:
(1) Completes a TODO in the code related to i18n handling of month and 
day names with auto-completion. Previously, when non-ASCII names were 
added to the auto-complete word list these had to be an exact 
case-sensitive match of the word to be auto-completed. This patch allows 
a case-insensitive match for non-ASCII names when deciding what names to 
add to the auto-complete list.
(2) Smarter auto-complete capitalization as described in OpenOffice bug 
22961. 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".
https://issues.apache.org/ooo/show_bug.cgi?id=22961
* The algorithm simply looks at the first character in the word to 
decide whether a word is sentence case.
* I've put a TODO in the code as SwAutoCompleteWord::GetRange() only 
performs an ASCII case-insensitive match (existing limitation).
* Sidenote - Initially I tried using CharClass::titlecase() but 
discovered this doesn't actually work. There appears to be an issue with 
class cclass_Unicode where "trans" is only ever set to 
"Transliteration_casemapping" and there is no mechanism to set it to 
"Transliteration_titlecase".
- make + make dev-install successful
- functionality tested ok
- licence statement on file
Cheers,
Brad
From 7f1e68f9a06bebd6690c8938b379508af96ab26c Mon Sep 17 00:00:00 2001
From: Brad Sowden <code@sowden.org>
Date: Mon, 4 Jun 2012 22:02:34 +1200
Subject: [PATCH 2/2] 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
---
 sw/source/ui/docvw/edtwin.cxx |  114 +++++++++++++++++++++++++----------------
 1 files changed, 70 insertions(+), 44 deletions(-)
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;
         }
     }
 }
-- 
1.7.7.6
Context
- [PATCH 2/2] Smarter auto-complete capitalization (#i22961#) and i18n	handling · Brad Sowden
 
   
 
  Privacy Policy |
  
Impressum (Legal Info) |
  
Copyright information: Unless otherwise specified, all text and images
  on this website are licensed under the
  
Creative Commons Attribution-Share Alike 3.0 License.
  This does not include the source code of LibreOffice, which is
  licensed under the Mozilla Public License (
MPLv2).
  "LibreOffice" and "The Document Foundation" are
  registered trademarks of their corresponding registered owners or are
  in actual use as trademarks in one or more countries. Their respective
  logos and icons are also subject to international copyright laws. Use
  thereof is explained in our 
trademark policy.