2 // System.Globalization.CultureInfo.cs
4 // Miguel de Icaza (miguel@ximian.com)
5 // Dick Porter (dick@ximian.com)
7 // (C) 2001, 2002, 2003 Ximian, Inc. (http://www.ximian.com)
10 using System.Collections;
11 using System.Threading;
12 using System.Runtime.CompilerServices;
14 namespace System.Globalization
17 public class CultureInfo : ICloneable, IFormatProvider
19 static CultureInfo invariant_culture_info;
31 bool m_useUserOverride;
32 NumberFormatInfo numInfo;
33 DateTimeFormatInfo dateTimeInfo;
35 private string m_name;
38 private string displayname;
40 private string englishname;
42 private string nativename;
44 private string iso3lang;
46 private string iso2lang;
48 private string icu_name;
50 private string win3lang;
51 CompareInfo compareInfo;
54 int m_dataItem; // MS.NET serializes this.
56 // Deserialized instances will set this to false
60 private static readonly string MSG_READONLY = "This instance is read only";
62 static public CultureInfo InvariantCulture {
64 if (invariant_culture_info == null) {
65 lock (typeof (CultureInfo)) {
66 if (invariant_culture_info == null) {
67 invariant_culture_info = new CultureInfo (0x7f, false);
68 invariant_culture_info.m_isReadOnly = true;
73 return(invariant_culture_info);
77 public static CultureInfo CreateSpecificCulture (string name)
80 throw new ArgumentNullException ("name");
83 if (name == String.Empty)
84 return InvariantCulture;
86 CultureInfo ci = new CultureInfo ();
87 if (!construct_internal_locale_from_specific_name (ci, name.ToLowerInvariant ()))
88 throw new ArgumentException ("Culture name " + name +
89 " is not supported.", name);
94 public static CultureInfo CurrentCulture
97 return Thread.CurrentThread.CurrentCulture;
101 public static CultureInfo CurrentUICulture
104 return Thread.CurrentThread.CurrentUICulture;
108 internal static CultureInfo ConstructCurrentCulture ()
110 CultureInfo ci = new CultureInfo ();
111 if (!construct_internal_locale_from_current_locale (ci))
112 ci = InvariantCulture;
116 internal static CultureInfo ConstructCurrentUICulture ()
118 return ConstructCurrentCulture ();
121 public virtual int LCID {
127 public virtual string Name {
133 public virtual string NativeName
136 if (!constructed) Construct ();
143 public virtual Calendar Calendar
145 get { return calendar; }
149 public virtual Calendar[] OptionalCalendars
156 public virtual CultureInfo Parent
159 if (!constructed) Construct ();
160 if (parent_lcid == cultureID)
162 return new CultureInfo (parent_lcid);
166 public virtual TextInfo TextInfo
169 if (textInfo == null) {
171 if(textInfo == null) {
172 textInfo = new TextInfo (cultureID);
181 public virtual string ThreeLetterISOLanguageName
184 if (!constructed) Construct ();
189 public virtual string ThreeLetterWindowsLanguageName
192 if (!constructed) Construct ();
197 public virtual string TwoLetterISOLanguageName
200 if (!constructed) Construct ();
205 public bool UseUserOverride
208 return m_useUserOverride;
212 internal string IcuName {
214 if (!constructed) Construct ();
219 public void ClearCachedData()
221 Thread.CurrentThread.CurrentCulture = null;
222 Thread.CurrentThread.CurrentUICulture = null;
225 public virtual object Clone()
227 if (!constructed) Construct ();
228 CultureInfo ci=(CultureInfo)MemberwiseClone ();
229 ci.m_isReadOnly=false;
233 public override bool Equals (object value)
235 CultureInfo b = value as CultureInfo;
238 return b.cultureID == cultureID;
242 public static CultureInfo[] GetCultures(CultureTypes types)
244 bool neutral=((types & CultureTypes.NeutralCultures)!=0);
245 bool specific=((types & CultureTypes.SpecificCultures)!=0);
246 bool installed=((types & CultureTypes.InstalledWin32Cultures)!=0); // TODO
248 return internal_get_cultures (neutral, specific, installed);
251 public override int GetHashCode()
256 public static CultureInfo ReadOnly(CultureInfo ci)
259 throw new ArgumentNullException("ci");
262 if(ci.m_isReadOnly) {
265 CultureInfo new_ci=(CultureInfo)ci.Clone ();
266 new_ci.m_isReadOnly=true;
271 public override string ToString()
276 public virtual CompareInfo CompareInfo
279 if (!constructed) Construct ();
280 if(compareInfo==null) {
282 if(compareInfo==null) {
283 compareInfo=new CompareInfo (this);
292 internal static bool IsIDNeutralCulture (int lcid)
295 if (!internal_is_lcid_neutral (lcid, out ret))
296 throw new ArgumentException (String.Format ("Culture id 0x{:x4} is not supported.", lcid));
301 public virtual bool IsNeutralCulture {
303 if (!constructed) Construct ();
304 return ((cultureID & 0xff00) == 0 || specific_lcid == 0);
308 public virtual NumberFormatInfo NumberFormat {
310 if (!constructed) Construct ();
311 if (numInfo == null){
313 if (numInfo == null) {
314 numInfo = new NumberFormatInfo ();
315 construct_number_format ();
324 if (!constructed) Construct ();
325 if (m_isReadOnly) throw new InvalidOperationException(MSG_READONLY);
328 throw new ArgumentNullException ("NumberFormat");
334 public virtual DateTimeFormatInfo DateTimeFormat
338 if (!constructed) Construct ();
339 if (dateTimeInfo == null)
343 if (dateTimeInfo == null) {
344 dateTimeInfo = new DateTimeFormatInfo();
345 construct_datetime_format ();
355 if (!constructed) Construct ();
356 if (m_isReadOnly) throw new InvalidOperationException(MSG_READONLY);
359 throw new ArgumentNullException ("DateTimeFormat");
361 dateTimeInfo = value;
365 public virtual string DisplayName
368 if (!constructed) Construct ();
373 public virtual string EnglishName
376 if (!constructed) Construct ();
382 public static CultureInfo InstalledUICulture
389 public bool IsReadOnly
392 return(m_isReadOnly);
398 // IFormatProvider implementation
400 public virtual object GetFormat( Type formatType )
402 object format = null;
404 if ( formatType == typeof(NumberFormatInfo) )
405 format = NumberFormat;
406 else if ( formatType == typeof(DateTimeFormatInfo) )
407 format = DateTimeFormat;
414 construct_internal_locale_from_lcid (cultureID);
418 [MethodImplAttribute (MethodImplOptions.InternalCall)]
419 private extern void construct_internal_locale (string locale);
421 [MethodImplAttribute (MethodImplOptions.InternalCall)]
422 private extern bool construct_internal_locale_from_lcid (int lcid);
424 [MethodImplAttribute (MethodImplOptions.InternalCall)]
425 private extern bool construct_internal_locale_from_name (string name);
427 [MethodImplAttribute (MethodImplOptions.InternalCall)]
428 private extern static bool construct_internal_locale_from_specific_name (CultureInfo ci,
431 [MethodImplAttribute (MethodImplOptions.InternalCall)]
432 private extern static bool construct_internal_locale_from_current_locale (CultureInfo ci);
434 [MethodImplAttribute (MethodImplOptions.InternalCall)]
435 private extern static CultureInfo [] internal_get_cultures (bool neutral, bool specific, bool installed);
437 [MethodImplAttribute (MethodImplOptions.InternalCall)]
438 private extern void construct_datetime_format ();
440 [MethodImplAttribute (MethodImplOptions.InternalCall)]
441 private extern void construct_number_format ();
443 // Returns false if the culture can not be found, sets is_neutral if it is
444 [MethodImplAttribute (MethodImplOptions.InternalCall)]
445 private extern static bool internal_is_lcid_neutral (int lcid, out bool is_neutral);
447 private void ConstructInvariant (bool use_user_override)
451 this.m_useUserOverride=use_user_override;
453 /* NumberFormatInfo defaults to the invariant data */
454 numInfo=new NumberFormatInfo ();
456 /* DateTimeFormatInfo defaults to the invariant data */
457 dateTimeInfo=new DateTimeFormatInfo ();
459 textInfo=new TextInfo ();
462 displayname="Invariant Language (Invariant Country)";
463 englishname="Invariant Language (Invariant Country)";
464 nativename="Invariant Language (Invariant Country)";
467 icu_name="en_US_POSIX";
471 public CultureInfo (int culture, bool use_user_override)
474 throw new ArgumentOutOfRangeException ("culture");
478 if(culture==0x007f) {
479 /* Short circuit the invariant culture */
480 ConstructInvariant (use_user_override);
484 if (!construct_internal_locale_from_lcid (culture))
485 throw new ArgumentException ("Culture name " + m_name +
486 " is not supported.", "name");
489 public CultureInfo (int culture) : this (culture, false) {}
491 public CultureInfo (string name, bool use_user_override)
494 throw new ArgumentNullException ();
499 /* Short circuit the invariant culture */
500 ConstructInvariant (use_user_override);
504 if (!construct_internal_locale_from_name (name.ToLowerInvariant ()))
505 throw new ArgumentException ("Culture name " + name +
506 " is not supported.", "name");
509 public CultureInfo (string name) : this (name, false) {}
511 // This is used when creating by specific name and creating by
512 // current locale so we can initialize the object without
513 // doing any member initialization
514 private CultureInfo () { constructed = true; }