~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/intl/locale/src/unix/nsCollationUnix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Pierre Phaneuf <pp@ludusdesign.com>
 
24
 *
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the NPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the NPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
#include  <locale.h>
 
41
#include "prmem.h"
 
42
#include "nsCollationUnix.h"
 
43
#include "nsIServiceManager.h"
 
44
#include "nsIComponentManager.h"
 
45
#include "nsLocaleCID.h"
 
46
#include "nsILocaleService.h"
 
47
#include "nsIPlatformCharset.h"
 
48
#include "nsIPosixLocale.h"
 
49
#include "nsCOMPtr.h"
 
50
#include "nsIPrefBranch.h"
 
51
#include "nsIPrefService.h"
 
52
#include "nsIPrefLocalizedString.h"
 
53
#include "nsUnicharUtils.h"
 
54
#include "nsCRT.h"
 
55
//#define DEBUG_UNIX_COLLATION
 
56
 
 
57
inline void nsCollationUnix::DoSetLocale()
 
58
{
 
59
  char *locale = setlocale(LC_COLLATE, NULL);
 
60
  mSavedLocale.Assign(locale ? locale : "");
 
61
  if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) {
 
62
    (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mLocale,0,MAX_LOCALE_LEN)).get());
 
63
  }
 
64
}
 
65
 
 
66
inline void nsCollationUnix::DoRestoreLocale()
 
67
{
 
68
  if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) { 
 
69
    (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mSavedLocale,0,MAX_LOCALE_LEN)).get());
 
70
  }
 
71
}
 
72
 
 
73
nsCollationUnix::nsCollationUnix() 
 
74
{
 
75
  mCollation = NULL;
 
76
  mUseCodePointOrder = PR_FALSE;
 
77
}
 
78
 
 
79
nsCollationUnix::~nsCollationUnix() 
 
80
{
 
81
  if (mCollation != NULL)
 
82
    delete mCollation;
 
83
}
 
84
 
 
85
NS_IMPL_ISUPPORTS1(nsCollationUnix, nsICollation)
 
86
 
 
87
nsresult nsCollationUnix::Initialize(nsILocale* locale) 
 
88
{
 
89
#define kPlatformLocaleLength 64
 
90
  NS_ASSERTION(mCollation == NULL, "Should only be initialized once");
 
91
 
 
92
  nsresult res;
 
93
 
 
94
  nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
95
  if (prefBranch) {
 
96
    nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
 
97
    res = prefBranch->GetComplexValue("intl.collationOption",
 
98
                                      NS_GET_IID(nsIPrefLocalizedString),
 
99
                                      getter_AddRefs(prefLocalString));
 
100
    if (NS_SUCCEEDED(res) && prefLocalString) {
 
101
      nsXPIDLString prefValue;
 
102
      prefLocalString->GetData(getter_Copies(prefValue));
 
103
      mUseCodePointOrder =
 
104
        prefValue.Equals(NS_LITERAL_STRING("useCodePointOrder"),
 
105
                         nsCaseInsensitiveStringComparator());
 
106
    }
 
107
  }
 
108
 
 
109
  mCollation = new nsCollation;
 
110
  if (mCollation == NULL) {
 
111
    NS_ASSERTION(0, "mCollation creation failed");
 
112
    return NS_ERROR_OUT_OF_MEMORY;
 
113
  }
 
114
 
 
115
  // default platform locale
 
116
  mLocale.Assign('C');
 
117
 
 
118
  nsAutoString localeStr;
 
119
  NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_COLLATE##PLATFORM");
 
120
 
 
121
  // get locale string, use app default if no locale specified
 
122
  if (locale == nsnull) {
 
123
    nsCOMPtr<nsILocaleService> localeService = 
 
124
             do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
 
125
    if (NS_SUCCEEDED(res)) {
 
126
      nsCOMPtr<nsILocale> appLocale;
 
127
      res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
 
128
      if (NS_SUCCEEDED(res)) {
 
129
        res = appLocale->GetCategory(aCategory, localeStr);
 
130
        NS_ASSERTION(NS_SUCCEEDED(res), "failed to get app locale info");
 
131
      }
 
132
    }
 
133
  }
 
134
  else {
 
135
    res = locale->GetCategory(aCategory, localeStr);
 
136
    NS_ASSERTION(NS_SUCCEEDED(res), "failed to get locale info");
 
137
  }
 
138
 
 
139
  // Get platform locale and charset name from locale, if available
 
140
  if (NS_SUCCEEDED(res)) {
 
141
    // keep the same behavior as 4.x as well as avoiding Linux collation key problem
 
142
    if (localeStr.EqualsIgnoreCase("en_US")) { // note: locale is in platform format
 
143
      localeStr.Assign(NS_LITERAL_STRING("C"));
 
144
    }
 
145
 
 
146
    nsCOMPtr <nsIPosixLocale> posixLocale = do_GetService(NS_POSIXLOCALE_CONTRACTID, &res);
 
147
    if (NS_SUCCEEDED(res)) {
 
148
      res = posixLocale->GetPlatformLocale(localeStr, mLocale);
 
149
    }
 
150
 
 
151
    nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &res);
 
152
    if (NS_SUCCEEDED(res)) {
 
153
      nsCAutoString mappedCharset;
 
154
      res = platformCharset->GetDefaultCharsetForLocale(localeStr, mappedCharset);
 
155
      if (NS_SUCCEEDED(res)) {
 
156
        mCollation->SetCharset(mappedCharset.get());
 
157
      }
 
158
    }
 
159
  }
 
160
 
 
161
  return NS_OK;
 
162
}
 
163
 
 
164
 
 
165
nsresult nsCollationUnix::CompareString(PRInt32 strength,
 
166
                                        const nsAString& string1,
 
167
                                        const nsAString& string2,
 
168
                                        PRInt32* result) 
 
169
{
 
170
  nsresult res = NS_OK;
 
171
 
 
172
  nsAutoString stringNormalized1, stringNormalized2;
 
173
  if (strength != kCollationCaseSensitive) {
 
174
    res = mCollation->NormalizeString(string1, stringNormalized1);
 
175
    if (NS_FAILED(res)) {
 
176
      return res;
 
177
    }
 
178
    res = mCollation->NormalizeString(string2, stringNormalized2);
 
179
    if (NS_FAILED(res)) {
 
180
      return res;
 
181
    }
 
182
  } else {
 
183
    stringNormalized1 = string1;
 
184
    stringNormalized2 = string2;
 
185
  }
 
186
 
 
187
  // convert unicode to charset
 
188
  char *str1, *str2;
 
189
 
 
190
  res = mCollation->UnicodeToChar(stringNormalized1, &str1);
 
191
  if (NS_SUCCEEDED(res) && str1 != NULL) {
 
192
    res = mCollation->UnicodeToChar(stringNormalized2, &str2);
 
193
    if (NS_SUCCEEDED(res) && str2 != NULL) {
 
194
      if (mUseCodePointOrder) {
 
195
        *result = strcmp(str1, str2);
 
196
      }
 
197
      else {
 
198
        DoSetLocale();
 
199
        *result = strcoll(str1, str2);
 
200
        DoRestoreLocale();
 
201
      }
 
202
      PR_Free(str2);
 
203
    }
 
204
    PR_Free(str1);
 
205
  }
 
206
 
 
207
  return res;
 
208
}
 
209
 
 
210
 
 
211
nsresult nsCollationUnix::AllocateRawSortKey(PRInt32 strength, 
 
212
                                             const nsAString& stringIn,
 
213
                                             PRUint8** key, PRUint32* outLen)
 
214
{
 
215
  nsresult res = NS_OK;
 
216
 
 
217
  nsAutoString stringNormalized;
 
218
  if (strength != kCollationCaseSensitive) {
 
219
    res = mCollation->NormalizeString(stringIn, stringNormalized);
 
220
    if (NS_FAILED(res))
 
221
      return res;
 
222
  } else {
 
223
    stringNormalized = stringIn;
 
224
  }
 
225
  // convert unicode to charset
 
226
  char *str;
 
227
 
 
228
  res = mCollation->UnicodeToChar(stringNormalized, &str);
 
229
  if (NS_SUCCEEDED(res) && str != NULL) {
 
230
    if (mUseCodePointOrder) {
 
231
      *key = (PRUint8 *)str;
 
232
      *outLen = strlen(str) + 1;
 
233
    } else {
 
234
      DoSetLocale();
 
235
      // call strxfrm to generate a key 
 
236
      size_t len = strxfrm(nsnull, str, 0) + 1;
 
237
      void *buffer = PR_Malloc(len);
 
238
      if (!buffer) {
 
239
        res = NS_ERROR_OUT_OF_MEMORY;
 
240
      } else if (strxfrm((char *)buffer, str, len) >= len) {
 
241
        PR_Free(buffer);
 
242
        res = NS_ERROR_FAILURE;
 
243
      } else {
 
244
        *key = (PRUint8 *)buffer;
 
245
        *outLen = len;
 
246
      }
 
247
      DoRestoreLocale();
 
248
      PR_Free(str);
 
249
    }
 
250
  }
 
251
 
 
252
  return res;
 
253
}
 
254
 
 
255
nsresult nsCollationUnix::CompareRawSortKey(const PRUint8* key1, PRUint32 len1, 
 
256
                                            const PRUint8* key2, PRUint32 len2, 
 
257
                                            PRInt32* result)
 
258
{
 
259
  *result = PL_strcmp((const char *)key1, (const char *)key2);
 
260
  return NS_OK;
 
261
}