Back to index

lightning-sunbird  0.9+nobinonly
nsCollationWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 
00040 #include "nsCollationWin.h"
00041 #include "nsIServiceManager.h"
00042 #include "nsIComponentManager.h"
00043 #include "nsLocaleCID.h"
00044 #include "nsILocaleService.h"
00045 #include "nsIPlatformCharset.h"
00046 #include "nsIWin32Locale.h"
00047 #include "nsCOMPtr.h"
00048 #include "prmem.h"
00049 #include "plstr.h"
00050 #include <windows.h>
00051 
00052 #ifdef WINCE
00053 #include <Winnls.h>
00054 #else
00055 #undef CompareString
00056 #endif
00057 
00058 NS_IMPL_ISUPPORTS1(nsCollationWin, nsICollation)
00059 
00060 
00061 nsCollationWin::nsCollationWin() 
00062 {
00063   mCollation = NULL;
00064 }
00065 
00066 nsCollationWin::~nsCollationWin() 
00067 {
00068   if (mCollation != NULL)
00069     delete mCollation;
00070 }
00071 
00072 nsresult nsCollationWin::Initialize(nsILocale* locale) 
00073 {
00074   NS_ASSERTION(mCollation == NULL, "Should only be initialized once.");
00075 
00076   nsresult res;
00077 
00078   mCollation = new nsCollation;
00079   if (!mCollation) {
00080     return NS_ERROR_OUT_OF_MEMORY;
00081   }
00082 
00083   OSVERSIONINFO os;
00084   os.dwOSVersionInfoSize = sizeof(os);
00085   ::GetVersionEx(&os);
00086   if (VER_PLATFORM_WIN32_NT == os.dwPlatformId && os.dwMajorVersion >= 4) {
00087     mW_API = PR_TRUE;
00088   }
00089   else {
00090     mW_API = PR_FALSE;
00091   }
00092   
00093   // default LCID (en-US)
00094   mLCID = 1033;
00095 
00096   nsAutoString localeStr;
00097 
00098   // get locale string, use app default if no locale specified
00099   if (!locale) {
00100     nsCOMPtr<nsILocaleService> localeService = 
00101              do_GetService(NS_LOCALESERVICE_CONTRACTID);
00102     if (localeService) {
00103       nsCOMPtr<nsILocale> appLocale;
00104       res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
00105       if (NS_SUCCEEDED(res)) {
00106         res = appLocale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), 
00107                                      localeStr);
00108       }
00109     }
00110   }
00111   else {
00112     res = locale->GetCategory(NS_LITERAL_STRING("NSILOCALE_COLLATE"), 
00113                               localeStr);
00114   }
00115 
00116   // Get LCID and charset name from locale, if available
00117   nsCOMPtr <nsIWin32Locale> win32Locale = 
00118       do_GetService(NS_WIN32LOCALE_CONTRACTID);
00119   if (win32Locale) {
00120     LCID lcid;
00121     res = win32Locale->GetPlatformLocale(localeStr, &lcid);
00122     if (NS_SUCCEEDED(res)) {
00123       mLCID = lcid;
00124     }
00125   }
00126 
00127   nsCOMPtr <nsIPlatformCharset> platformCharset = 
00128       do_GetService(NS_PLATFORMCHARSET_CONTRACTID);
00129   if (platformCharset) {
00130     nsCAutoString mappedCharset;
00131     res = platformCharset->GetDefaultCharsetForLocale(localeStr, mappedCharset);
00132     if (NS_SUCCEEDED(res)) {
00133       mCollation->SetCharset(mappedCharset.get());
00134     }
00135   }
00136 
00137   return NS_OK;
00138 }
00139 
00140 
00141 NS_IMETHODIMP nsCollationWin::CompareString(PRInt32 strength, 
00142                                             const nsAString & string1, 
00143                                             const nsAString & string2, 
00144                                             PRInt32 *result)
00145 {
00146   int retval;
00147   nsresult res;
00148   DWORD dwMapFlags = 0;
00149 
00150 #ifndef WINCE // NORM_IGNORECASE is not supported on WINCE
00151   if (strength == kCollationCaseInSensitive)
00152     dwMapFlags |= NORM_IGNORECASE;
00153 
00154   if (mW_API) {
00155 #endif
00156     retval = ::CompareStringW(mLCID, 
00157                               dwMapFlags,
00158                               (LPCWSTR) PromiseFlatString(string1).get(), 
00159                               -1,
00160                               (LPCWSTR) PromiseFlatString(string2).get(), 
00161                               -1);
00162     if (retval) {
00163       res = NS_OK;
00164       *result = retval - 2;
00165     } else {
00166       res = NS_ERROR_FAILURE;
00167     }
00168 #ifndef WINCE // Always use wide APIs on Win CE.
00169   } else {
00170     char *Cstr1 = nsnull, *Cstr2 = nsnull;
00171     res = mCollation->UnicodeToChar(string1, &Cstr1);
00172     if (NS_SUCCEEDED(res) && Cstr1 != nsnull) {
00173       res = mCollation->UnicodeToChar(string2, &Cstr2);
00174       if (NS_SUCCEEDED(res) && Cstr2 != nsnull) {
00175         retval = CompareStringA(mLCID, dwMapFlags, Cstr1, -1, Cstr2, -1);
00176         if (retval)
00177           *result = retval - 2;
00178         else
00179           res = NS_ERROR_FAILURE;
00180         PR_Free(Cstr2);
00181       }
00182       PR_Free(Cstr1);
00183     }
00184   }
00185 #endif //WINCE
00186 
00187   return res;
00188 }
00189  
00190 
00191 nsresult nsCollationWin::AllocateRawSortKey(PRInt32 strength, 
00192                                             const nsAString& stringIn, PRUint8** key, PRUint32* outLen)
00193 {
00194   int byteLen;
00195   void *buffer;
00196   nsresult res = NS_OK;
00197   DWORD dwMapFlags = LCMAP_SORTKEY;
00198 
00199   if (strength == kCollationCaseInSensitive)
00200     dwMapFlags |= NORM_IGNORECASE;
00201 
00202 #ifndef WINCE // Always use wide APIs on Win CE.
00203   if (mW_API) {
00204 #endif
00205     byteLen = LCMapStringW(mLCID, dwMapFlags, 
00206                            (LPCWSTR) PromiseFlatString(stringIn).get(),
00207                            -1, NULL, 0);
00208     buffer = PR_Malloc(byteLen);
00209     if (!buffer) {
00210       res = NS_ERROR_OUT_OF_MEMORY;
00211     } else {
00212       *key = (PRUint8 *)buffer;
00213       *outLen = LCMapStringW(mLCID, dwMapFlags, 
00214                              (LPCWSTR) PromiseFlatString(stringIn).get(),
00215                              -1, (LPWSTR) buffer, byteLen);
00216     }
00217 #ifndef WINCE // Always use wide APIs on Win CE.
00218   }
00219   else {
00220     char *Cstr = nsnull;
00221     res = mCollation->UnicodeToChar(stringIn, &Cstr);
00222     if (NS_SUCCEEDED(res) && Cstr != nsnull) {
00223       byteLen = LCMapStringA(mLCID, dwMapFlags, Cstr, -1, NULL, 0);
00224       buffer = PR_Malloc(byteLen);
00225       if (!buffer) {
00226         res = NS_ERROR_OUT_OF_MEMORY;
00227       } else {
00228         *key = (PRUint8 *)buffer;
00229         *outLen = LCMapStringA(mLCID, dwMapFlags, Cstr, -1, (char *) buffer, byteLen);
00230       }
00231       PR_Free(Cstr);
00232     }
00233   }
00234 #endif
00235   return res;
00236 }
00237 
00238 nsresult nsCollationWin::CompareRawSortKey(const PRUint8* key1, PRUint32 len1, 
00239                                            const PRUint8* key2, PRUint32 len2, 
00240                                            PRInt32* result)
00241 {
00242   *result = PL_strcmp((const char *)key1, (const char *)key2);
00243   return NS_OK;
00244 }