using System; using System.Globalization; using System.Runtime.InteropServices; namespace Vanara.PInvoke { /// /// An LCID is a 4-byte value. The value supplied in an LCID is a standard numeric substitution for the international [RFC5646] string. /// /// /// /// /// /// /// /// [StructLayout(LayoutKind.Sequential)] [PInvokeData("winnls.h")] public partial struct LCID : IComparable, IComparable, IConvertible, IEquatable, IEquatable { /// Sort order identifiers. public enum SORT : byte { /// sorting default SORT_DEFAULT = 0x0, /// Invariant (Mathematical Symbols) SORT_INVARIANT_MATH = 0x1, /// Japanese XJIS order SORT_JAPANESE_XJIS = 0x0, /// Japanese Unicode order (no longer supported) SORT_JAPANESE_UNICODE = 0x1, /// Japanese radical/stroke order SORT_JAPANESE_RADICALSTROKE = 0x4, /// Chinese BIG5 order SORT_CHINESE_BIG5 = 0x0, /// PRC Chinese Phonetic order SORT_CHINESE_PRCP = 0x0, /// Chinese Unicode order (no longer supported) SORT_CHINESE_UNICODE = 0x1, /// PRC Chinese Stroke Count order SORT_CHINESE_PRC = 0x2, /// Traditional Chinese Bopomofo order SORT_CHINESE_BOPOMOFO = 0x3, /// Traditional Chinese radical/stroke order. SORT_CHINESE_RADICALSTROKE = 0x4, /// Korean KSC order SORT_KOREAN_KSC = 0x0, /// Korean Unicode order (no longer supported) SORT_KOREAN_UNICODE = 0x1, /// German Phone Book order SORT_GERMAN_PHONE_BOOK = 0x1, /// Hungarian Default order SORT_HUNGARIAN_DEFAULT = 0x0, /// Hungarian Technical order SORT_HUNGARIAN_TECHNICAL = 0x1, /// Georgian Traditional order SORT_GEORGIAN_TRADITIONAL = 0x0, /// Georgian Modern order SORT_GEORGIAN_MODERN = 0x1, } internal uint _value; private const int langMask = 0x0FFFF; private const uint sortMask = 0xF0000; private const int sortShift = 16; /// Initializes a new instance of the structure. /// The raw LCID value. public LCID(uint rawValue) => _value = rawValue; /// Initializes a new instance of the structure. /// /// Language identifier. This parameter is a combination of a primary language identifier and a sublanguage identifier. /// /// Sort order identifier. public LCID(LANGID lgid, SORT srtid) => _value = (((uint)(ushort)srtid) << sortShift) | lgid; /// Retrieves a language identifier from a locale identifier. public LANGID LANGID => (LANGID)_value; /// Retrieves a sort order identifier from a locale identifier. public SORT SORTID => (SORT)(((_value) >> sortShift) & 0xf); /// Gets the value. /// The value. public uint Value { get => _value; private set => _value = value; } /// Compares the current object with another object of the same type. /// An object to compare with this object. /// /// A value that indicates the relative order of the objects being compared. The return value has the following /// meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal /// to . Greater than zero This object is greater than . /// public int CompareTo(LCID other) => _value.CompareTo(other._value); /// /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current /// instance precedes, follows, or occurs in the same position in the sort order as the other object. /// /// An object to compare with this instance. /// /// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less /// than zero This instance precedes in the sort order. Zero This instance occurs in the same position in the /// sort order as . Greater than zero This instance follows in the sort order. /// public int CompareTo(object obj) => obj is IConvertible c ? _value.CompareTo(c.ToUInt32(null)) : throw new ArgumentException(@"Object cannot be converted to a UInt32 value for comparison.", nameof(obj)); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) => obj is IConvertible c && _value.Equals(c.ToUInt32(null)); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(LCID other) => other._value == _value; /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(uint other) => other == _value; /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => _value.GetHashCode(); /// public TypeCode GetTypeCode() => Value.GetTypeCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => ToString(CultureInfo.InvariantCulture); /// public string ToString(IFormatProvider provider) => string.Format(provider, "0x{0:X8}", _value); /// Implements the operator ==. /// The first . /// The second . /// The result of the operator. public static bool operator ==(LCID hrLeft, LCID hrRight) => hrLeft._value == hrRight._value; /// Implements the operator ==. /// The first . /// The second . /// The result of the operator. public static bool operator ==(LCID hrLeft, uint hrRight) => hrLeft._value == hrRight; /// Implements the operator !=. /// The first . /// The second . /// The result of the operator. public static bool operator !=(LCID hrLeft, LCID hrRight) => !(hrLeft == hrRight); /// Implements the operator !=. /// The first . /// The second . /// The result of the operator. public static bool operator !=(LCID hrLeft, uint hrRight) => !(hrLeft == hrRight); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator LCID(uint value) => new(value); /// Performs an explicit conversion from to . /// The value. /// The result of the conversion. public static explicit operator uint(LCID value) => value._value; /// The default locale for the operating system. The value of this constant is 0x0800. public static LCID LOCALE_SYSTEM_DEFAULT = new(LANGID.LANG_SYSTEM_DEFAULT, SORT.SORT_DEFAULT); /// The default locale for the user or process. The value of this constant is 0x0400. public static LCID LOCALE_USER_DEFAULT = new(LANGID.LANG_USER_DEFAULT, SORT.SORT_DEFAULT); /// /// Windows Vista and later: The default custom locale. When an NLS function must return a locale identifier for a supplemental /// locale for the current user, the function returns this value instead of LOCALE_USER_DEFAULT. The value of LOCALE_CUSTOM_DEFAULT /// is 0x0C00. /// public static LCID LOCALE_CUSTOM_DEFAULT => new(new LANGID(LANGID.LANG.LANG_NEUTRAL, LANGID.SUBLANG.SUBLANG_CUSTOM_DEFAULT), SORT.SORT_DEFAULT); /// /// Windows Vista and later: An unspecified custom locale, used to identify all supplemental locales except the locale for the /// current user. Supplemental locales cannot be distinguished from one another by their locale identifiers, but can be /// distinguished by their locale names. Certain NLS functions can return this constant to indicate that they cannot provide a /// useful identifier for a particular locale. The value of LOCALE_CUSTOM_UNSPECIFIED is 0x1000. /// public static LCID LOCALE_CUSTOM_UNSPECIFIED => new(new LANGID(LANGID.LANG.LANG_NEUTRAL, LANGID.SUBLANG.SUBLANG_CUSTOM_UNSPECIFIED), SORT.SORT_DEFAULT); /// /// Windows Vista and later: The default custom locale for MUI. The user preferred UI languages and the system preferred UI /// languages can include at most a single language that is implemented by a Language Interface Pack (LIP) and for which the /// language identifier corresponds to a supplemental locale. If there is such a language in a list, the constant is used to refer /// to that language in certain contexts. The value of LOCALE_CUSTOM_UI_DEFAULT is 0x1400. /// public static LCID LOCALE_CUSTOM_UI_DEFAULT => new(new LANGID(LANGID.LANG.LANG_NEUTRAL, LANGID.SUBLANG.SUBLANG_UI_CUSTOM_DEFAULT), SORT.SORT_DEFAULT); /// /// The neutral locale. This constant is generally not used when calling NLS APIs. Instead, use either LOCALE_SYSTEM_DEFAULT or /// LOCALE_USER_DEFAULT. The value of LOCALE_NEUTRAL is 0x0000. /// public static LCID LOCALE_NEUTRAL => new(new LANGID(LANGID.LANG.LANG_NEUTRAL, LANGID.SUBLANG.SUBLANG_NEUTRAL), SORT.SORT_DEFAULT); /// /// Windows XP: The locale used for operating system-level functions that require consistent and locale-independent results. For /// example, the invariant locale is used when an application compares character strings using the CompareString function and /// expects a consistent result regardless of the user locale. The settings of the invariant locale are similar to those for English /// (United States) but should not be used to display formatted data. Typically, an application does not use LOCALE_INVARIANT /// because it expects the results of an action to depend on the rules governing each individual locale. The value of /// LOCALE_INVARIANT IS 0x007f. /// public static LCID LOCALE_INVARIANT => new(new LANGID(LANGID.LANG.LANG_INVARIANT, LANGID.SUBLANG.SUBLANG_NEUTRAL), SORT.SORT_DEFAULT); /// bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider); /// byte IConvertible.ToByte(IFormatProvider provider) => ((IConvertible)Value).ToByte(provider); /// char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)Value).ToChar(provider); /// DateTime IConvertible.ToDateTime(IFormatProvider provider) => ((IConvertible)Value).ToDateTime(provider); /// decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)Value).ToDecimal(provider); /// double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)Value).ToDouble(provider); /// short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)Value).ToInt16(provider); /// int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)Value).ToInt32(provider); /// long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)Value).ToInt64(provider); /// sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)Value).ToSByte(provider); /// float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)Value).ToSingle(provider); /// object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider); /// ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)Value).ToUInt16(provider); /// uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)Value).ToUInt32(provider); /// ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)Value).ToUInt64(provider); } }