Bug 574821 - Add titlebar margin to browser-aero css for maximized windows - addresse...
[mozilla-central.git] / intl / uconv / src / nsCharsetConverterManager.cpp
blobb07e57c7f4dfb61e6fa68faa6bb07a90cf529965
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
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.
15 * The Original Code is Mozilla Communicator client code.
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.
22 * Contributor(s):
23 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsCOMPtr.h"
40 #include "nsString.h"
41 #include "nsReadableUtils.h"
42 #include "nsUnicharUtils.h"
43 #include "nsICharsetAlias.h"
44 #include "nsIServiceManager.h"
45 #include "nsICategoryManager.h"
46 #include "nsICharsetConverterManager.h"
47 #include "nsEncoderDecoderUtils.h"
48 #include "nsIStringBundle.h"
49 #include "nsUConvDll.h"
50 #include "prmem.h"
51 #include "nsCRT.h"
52 #include "nsTArray.h"
53 #include "nsStringEnumerator.h"
54 #include "nsThreadUtils.h"
55 #include "mozilla/Services.h"
57 #include "nsXPCOM.h"
58 #include "nsISupportsPrimitives.h"
60 // just for CONTRACTIDs
61 #include "nsCharsetConverterManager.h"
63 #ifdef MOZ_USE_NATIVE_UCONV
64 #include "nsNativeUConvService.h"
65 #endif
67 // Class nsCharsetConverterManager [implementation]
69 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager,
70 nsICharsetConverterManager)
72 nsCharsetConverterManager::nsCharsetConverterManager()
73 : mDataBundle(NULL)
74 , mTitleBundle(NULL)
76 #ifdef MOZ_USE_NATIVE_UCONV
77 mNativeUC = do_GetService(NS_NATIVE_UCONV_SERVICE_CONTRACT_ID);
78 #endif
81 nsCharsetConverterManager::~nsCharsetConverterManager()
83 NS_IF_RELEASE(mDataBundle);
84 NS_IF_RELEASE(mTitleBundle);
87 nsresult nsCharsetConverterManager::RegisterConverterManagerData()
89 nsresult rv;
90 nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
91 if (NS_FAILED(rv))
92 return rv;
94 RegisterConverterCategory(catman, NS_TITLE_BUNDLE_CATEGORY,
95 "chrome://global/locale/charsetTitles.properties");
96 RegisterConverterCategory(catman, NS_DATA_BUNDLE_CATEGORY,
97 "resource://gre-resources/charsetData.properties");
99 return NS_OK;
102 nsresult
103 nsCharsetConverterManager::RegisterConverterCategory(nsICategoryManager* catman,
104 const char* aCategory,
105 const char* aURL)
107 return catman->AddCategoryEntry(aCategory, aURL, "",
108 PR_TRUE, PR_TRUE, nsnull);
111 nsresult nsCharsetConverterManager::LoadExtensibleBundle(
112 const char* aCategory,
113 nsIStringBundle ** aResult)
115 nsCOMPtr<nsIStringBundleService> sbServ =
116 mozilla::services::GetStringBundleService();
117 if (!sbServ)
118 return NS_ERROR_FAILURE;
120 return sbServ->CreateExtensibleBundle(aCategory, aResult);
123 nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
124 const char * aName,
125 const nsAFlatString& aProp,
126 PRUnichar ** aResult)
128 nsAutoString key;
130 key.AssignWithConversion(aName);
131 ToLowerCase(key); // we lowercase the main comparison key
132 key.Append(aProp);
134 return aBundle->GetStringFromName(key.get(), aResult);
137 nsresult nsCharsetConverterManager::GetBundleValue(nsIStringBundle * aBundle,
138 const char * aName,
139 const nsAFlatString& aProp,
140 nsAString& aResult)
142 nsresult rv = NS_OK;
144 nsXPIDLString value;
145 rv = GetBundleValue(aBundle, aName, aProp, getter_Copies(value));
146 if (NS_FAILED(rv))
147 return rv;
149 aResult = value;
151 return NS_OK;
155 //----------------------------------------------------------------------------//----------------------------------------------------------------------------
156 // Interface nsICharsetConverterManager [implementation]
158 NS_IMETHODIMP
159 nsCharsetConverterManager::GetUnicodeEncoder(const char * aDest,
160 nsIUnicodeEncoder ** aResult)
162 // resolve the charset first
163 nsCAutoString charset;
165 // fully qualify to possibly avoid vtable call
166 nsCharsetConverterManager::GetCharsetAlias(aDest, charset);
168 return nsCharsetConverterManager::GetUnicodeEncoderRaw(charset.get(),
169 aResult);
173 NS_IMETHODIMP
174 nsCharsetConverterManager::GetUnicodeEncoderRaw(const char * aDest,
175 nsIUnicodeEncoder ** aResult)
177 *aResult= nsnull;
178 nsCOMPtr<nsIUnicodeEncoder> encoder;
180 #ifdef MOZ_USE_NATIVE_UCONV
181 if (mNativeUC) {
182 nsCOMPtr<nsISupports> supports;
183 mNativeUC->GetNativeConverter("UCS-2",
184 aDest,
185 getter_AddRefs(supports));
187 encoder = do_QueryInterface(supports);
189 if (encoder) {
190 NS_ADDREF(*aResult = encoder);
191 return NS_OK;
194 #endif
195 nsresult rv = NS_OK;
197 nsCAutoString
198 contractid(NS_LITERAL_CSTRING(NS_UNICODEENCODER_CONTRACTID_BASE) +
199 nsDependentCString(aDest));
201 // Always create an instance since encoders hold state.
202 encoder = do_CreateInstance(contractid.get(), &rv);
204 if (NS_FAILED(rv))
205 rv = NS_ERROR_UCONV_NOCONV;
206 else
208 *aResult = encoder.get();
209 NS_ADDREF(*aResult);
211 return rv;
214 NS_IMETHODIMP
215 nsCharsetConverterManager::GetUnicodeDecoder(const char * aSrc,
216 nsIUnicodeDecoder ** aResult)
218 // resolve the charset first
219 nsCAutoString charset;
221 // fully qualify to possibly avoid vtable call
222 nsCharsetConverterManager::GetCharsetAlias(aSrc, charset);
224 return nsCharsetConverterManager::GetUnicodeDecoderRaw(charset.get(),
225 aResult);
228 NS_IMETHODIMP
229 nsCharsetConverterManager::GetUnicodeDecoderRaw(const char * aSrc,
230 nsIUnicodeDecoder ** aResult)
232 *aResult= nsnull;
233 nsCOMPtr<nsIUnicodeDecoder> decoder;
235 #ifdef MOZ_USE_NATIVE_UCONV
236 if (mNativeUC) {
237 nsCOMPtr<nsISupports> supports;
238 mNativeUC->GetNativeConverter(aSrc,
239 "UCS-2",
240 getter_AddRefs(supports));
242 decoder = do_QueryInterface(supports);
244 if (decoder) {
245 NS_ADDREF(*aResult = decoder);
246 return NS_OK;
249 #endif
250 nsresult rv = NS_OK;
252 NS_NAMED_LITERAL_CSTRING(contractbase, NS_UNICODEDECODER_CONTRACTID_BASE);
253 nsDependentCString src(aSrc);
255 decoder = do_CreateInstance(PromiseFlatCString(contractbase + src).get(),
256 &rv);
257 NS_ENSURE_SUCCESS(rv, NS_ERROR_UCONV_NOCONV);
259 decoder.forget(aResult);
260 return rv;
263 nsresult
264 nsCharsetConverterManager::GetList(const nsACString& aCategory,
265 const nsACString& aPrefix,
266 nsIUTF8StringEnumerator** aResult)
268 if (aResult == NULL)
269 return NS_ERROR_NULL_POINTER;
270 *aResult = NULL;
272 nsresult rv;
273 nsCAutoString alias;
275 nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
276 if (NS_FAILED(rv))
277 return rv;
279 nsTArray<nsCString>* array = new nsTArray<nsCString>;
280 if (!array)
281 return NS_ERROR_OUT_OF_MEMORY;
283 nsCOMPtr<nsISimpleEnumerator> enumerator;
284 catman->EnumerateCategory(PromiseFlatCString(aCategory).get(),
285 getter_AddRefs(enumerator));
287 PRBool hasMore;
288 while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
289 nsCOMPtr<nsISupports> supports;
290 if (NS_FAILED(enumerator->GetNext(getter_AddRefs(supports))))
291 continue;
293 nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports);
294 if (!supStr)
295 continue;
297 nsCAutoString fullName(aPrefix);
299 nsCAutoString name;
300 if (NS_FAILED(supStr->GetData(name)))
301 continue;
303 fullName += name;
304 rv = GetCharsetAlias(fullName.get(), alias);
305 if (NS_FAILED(rv))
306 continue;
308 rv = array->AppendElement(alias) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
311 return NS_NewAdoptingUTF8StringEnumerator(aResult, array);
314 // we should change the interface so that we can just pass back a enumerator!
315 NS_IMETHODIMP
316 nsCharsetConverterManager::GetDecoderList(nsIUTF8StringEnumerator ** aResult)
318 return GetList(NS_LITERAL_CSTRING(NS_UNICODEDECODER_NAME),
319 EmptyCString(), aResult);
322 NS_IMETHODIMP
323 nsCharsetConverterManager::GetEncoderList(nsIUTF8StringEnumerator ** aResult)
325 return GetList(NS_LITERAL_CSTRING(NS_UNICODEENCODER_NAME),
326 EmptyCString(), aResult);
329 NS_IMETHODIMP
330 nsCharsetConverterManager::GetCharsetDetectorList(nsIUTF8StringEnumerator** aResult)
332 return GetList(NS_LITERAL_CSTRING("charset-detectors"),
333 NS_LITERAL_CSTRING("chardet."), aResult);
336 // XXX Improve the implementation of this method. Right now, it is build on
337 // top of the nsCharsetAlias service. We can make the nsCharsetAlias
338 // better, with its own hash table (not the StringBundle anymore) and
339 // a nicer file format.
340 NS_IMETHODIMP
341 nsCharsetConverterManager::GetCharsetAlias(const char * aCharset,
342 nsACString& aResult)
344 NS_PRECONDITION(aCharset, "null param");
345 if (!aCharset)
346 return NS_ERROR_NULL_POINTER;
348 // We try to obtain the preferred name for this charset from the charset
349 // aliases. If we don't get it from there, we just use the original string
350 nsDependentCString charset(aCharset);
351 nsCOMPtr<nsICharsetAlias> csAlias(do_GetService(NS_CHARSETALIAS_CONTRACTID));
352 NS_ASSERTION(csAlias, "failed to get the CharsetAlias service");
353 if (csAlias) {
354 nsAutoString pref;
355 nsresult rv = csAlias->GetPreferred(charset, aResult);
356 if (NS_SUCCEEDED(rv)) {
357 return (!aResult.IsEmpty()) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
361 aResult = charset;
362 return NS_OK;
366 NS_IMETHODIMP
367 nsCharsetConverterManager::GetCharsetTitle(const char * aCharset,
368 nsAString& aResult)
370 if (aCharset == NULL) return NS_ERROR_NULL_POINTER;
372 if (mTitleBundle == NULL) {
373 nsresult rv = LoadExtensibleBundle(NS_TITLE_BUNDLE_CATEGORY, &mTitleBundle);
374 if (NS_FAILED(rv))
375 return rv;
378 return GetBundleValue(mTitleBundle, aCharset, NS_LITERAL_STRING(".title"), aResult);
381 NS_IMETHODIMP
382 nsCharsetConverterManager::GetCharsetData(const char * aCharset,
383 const PRUnichar * aProp,
384 nsAString& aResult)
386 if (aCharset == NULL)
387 return NS_ERROR_NULL_POINTER;
388 // aProp can be NULL
390 if (mDataBundle == NULL) {
391 nsresult rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
392 if (NS_FAILED(rv))
393 return rv;
396 return GetBundleValue(mDataBundle, aCharset, nsDependentString(aProp), aResult);
399 NS_IMETHODIMP
400 nsCharsetConverterManager::GetCharsetLangGroup(const char * aCharset,
401 nsIAtom** aResult)
403 // resolve the charset first
404 nsCAutoString charset;
406 nsresult rv = GetCharsetAlias(aCharset, charset);
407 if (NS_FAILED(rv))
408 return rv;
410 // fully qualify to possibly avoid vtable call
411 return nsCharsetConverterManager::GetCharsetLangGroupRaw(charset.get(),
412 aResult);
415 NS_IMETHODIMP
416 nsCharsetConverterManager::GetCharsetLangGroupRaw(const char * aCharset,
417 nsIAtom** aResult)
420 *aResult = nsnull;
421 if (aCharset == NULL)
422 return NS_ERROR_NULL_POINTER;
424 nsresult rv = NS_OK;
426 if (mDataBundle == NULL) {
427 rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
428 if (NS_FAILED(rv))
429 return rv;
432 nsAutoString langGroup;
433 rv = GetBundleValue(mDataBundle, aCharset, NS_LITERAL_STRING(".LangGroup"), langGroup);
435 if (NS_SUCCEEDED(rv)) {
436 ToLowerCase(langGroup); // use lowercase for all language atoms
437 *aResult = NS_NewAtom(langGroup);
440 return rv;