diff --git a/UnicodeCharacterInspector/CharacterInfoViewModel.cs b/UnicodeCharacterInspector/CharacterInfoViewModel.cs
index 25e2120..b71a70f 100644
--- a/UnicodeCharacterInspector/CharacterInfoViewModel.cs
+++ b/UnicodeCharacterInspector/CharacterInfoViewModel.cs
@@ -55,6 +55,8 @@ namespace UnicodeCharacterInspector
NotifyPropertyChanged("Category");
NotifyPropertyChanged("CanonicalCombiningClass");
NotifyPropertyChanged("BidirectionalClass");
+ NotifyPropertyChanged("DecompositionType");
+ NotifyPropertyChanged("DecompositionMapping");
NotifyPropertyChanged("NumericType");
NotifyPropertyChanged("NumericValue");
NotifyPropertyChanged("ContributoryProperties");
@@ -92,6 +94,16 @@ namespace UnicodeCharacterInspector
get { return character != null && characterData != null ? characterData.BidirectionalClass : null as BidirectionalClass?; }
}
+ public CompatibilityFormattingTag? DecompositionType
+ {
+ get { return character != null && characterData != null && characterData.DecompositionMapping != null ? characterData.DecompositionType : null as CompatibilityFormattingTag?; }
+ }
+
+ public string DecompositionMapping
+ {
+ get { return character != null && characterData != null ? characterData.DecompositionMapping : null; }
+ }
+
public UnicodeNumericType? NumericType
{
get { return character != null ? characterData != null ? characterData.NumericType : UnicodeNumericType.None : null as UnicodeNumericType?; }
diff --git a/UnicodeCharacterInspector/MainWindow.xaml b/UnicodeCharacterInspector/MainWindow.xaml
index 33e71a6..3cec927 100644
--- a/UnicodeCharacterInspector/MainWindow.xaml
+++ b/UnicodeCharacterInspector/MainWindow.xaml
@@ -67,6 +67,8 @@
+
+
@@ -81,12 +83,16 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/UnicodeInformation.Builder/CharacterDecompositionMapping.cs b/UnicodeInformation.Builder/CharacterDecompositionMapping.cs
new file mode 100644
index 0000000..17ded32
--- /dev/null
+++ b/UnicodeInformation.Builder/CharacterDecompositionMapping.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace System.Unicode.Builder
+{
+ public struct CharacterDecompositionMapping
+ {
+ public readonly CompatibilityFormattingTag DecompositionType;
+ public readonly string DecompositionMapping;
+
+ public CharacterDecompositionMapping(CompatibilityFormattingTag decompositionType, string decompositionMapping)
+ {
+ this.DecompositionType = decompositionType;
+ this.DecompositionMapping = decompositionMapping;
+ }
+
+ public unsafe static CharacterDecompositionMapping Parse(string s)
+ {
+ if (string.IsNullOrEmpty(s)) return default(CharacterDecompositionMapping);
+
+ CompatibilityFormattingTag tag = CompatibilityFormattingTag.Canonical;
+
+ int index;
+
+ if (s[0] == '<')
+ {
+ if (!EnumHelper.TryGetNamedValue(s.Substring(1, (index = s.IndexOf('>')) - 1), out tag))
+ throw new FormatException();
+ ++index;
+ }
+ else
+ {
+ index = 0;
+ }
+
+ var buffer = stackalloc char[36]; // From the Unicode docs, a decomposition cannot have more than 18 code points.
+ int charIndex = 0;
+
+ while (index < s.Length && charIndex < 35)
+ {
+ char c = s[index];
+
+ if (c == ' ') ++index;
+ else
+ {
+ int codePoint = ParseCodePoint(s, ref index);
+
+ if (codePoint < 0x10000)
+ buffer[charIndex++] = (char)codePoint;
+ else if (codePoint < 0x10FFFF)
+ {
+ codePoint -= 0x10000;
+ buffer[charIndex++] = (char)((codePoint >> 10) + 0xD800);
+ buffer[charIndex++] = (char)((codePoint & 0x3FF) + 0xDC00);
+ }
+ else
+ {
+ throw new FormatException("The code point was outside of the allowed range.");
+ }
+ }
+ }
+
+ return new CharacterDecompositionMapping(tag, new string(buffer, 0, charIndex));
+ }
+
+ private static int ParseCodePoint(string s, ref int index)
+ {
+ int i = index;
+ int accum = 0;
+
+ while (i < s.Length)
+ {
+ char c = s[i];
+
+ if (c == ' ') break;
+
+ accum <<= 4;
+
+ if (c >= '0' && c <= '9') accum |= c - '0';
+ else if (c >= 'A' && c <= 'F') accum |= c - 'A' + 0xA;
+ else if (c >= 'a' && c <= 'f') accum |= c - 'a' + 0xA;
+ else throw new FormatException();
+
+ ++i;
+ }
+
+ index = i;
+ return accum;
+ }
+ }
+}
diff --git a/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs b/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
index bf8f5ab..3f300f1 100644
--- a/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
+++ b/UnicodeInformation.Builder/UnicodeCharacterDataBuilder.cs
@@ -15,7 +15,7 @@ namespace System.Unicode.Builder
private UnicodeCategory category = UnicodeCategory.OtherNotAssigned;
private CanonicalCombiningClass canonicalCombiningClass;
private BidirectionalClass bidirectionalClass;
- private string decompositionType;
+ private CharacterDecompositionMapping characterDecompositionMapping;
private UnicodeNumericType numericType;
private UnicodeRationalNumber numericValue;
private bool bidirectionalMirrored;
@@ -60,10 +60,10 @@ namespace System.Unicode.Builder
set { bidirectionalClass = value; }
}
- public string DecompositionType
+ public CharacterDecompositionMapping CharacterDecompositionMapping
{
- get { return decompositionType; }
- set { decompositionType = value; }
+ get { return characterDecompositionMapping; }
+ set { characterDecompositionMapping = value; }
}
public UnicodeNumericType NumericType
@@ -136,7 +136,8 @@ namespace System.Unicode.Builder
category,
canonicalCombiningClass,
bidirectionalClass,
- decompositionType,
+ characterDecompositionMapping.DecompositionType,
+ characterDecompositionMapping.DecompositionMapping,
numericType,
numericValue,
bidirectionalMirrored,
@@ -159,7 +160,7 @@ namespace System.Unicode.Builder
if (category != UnicodeCategory.OtherNotAssigned) fields |= UcdFields.Category;
if (canonicalCombiningClass != CanonicalCombiningClass.NotReordered) fields |= UcdFields.CanonicalCombiningClass;
/*if (bidirectionalClass != 0)*/fields |= UcdFields.BidirectionalClass;
- if (decompositionType != null) fields |= UcdFields.DecompositionType;
+ if (characterDecompositionMapping.DecompositionMapping != null) fields |= UcdFields.DecompositionMapping;
fields |= (UcdFields)((int)numericType << 6);
if (bidirectionalMirrored) fields |= UcdFields.BidirectionalMirrored;
if (oldName != null) fields |= UcdFields.OldName;
@@ -177,7 +178,11 @@ namespace System.Unicode.Builder
if ((fields & UcdFields.Category) != 0) writer.Write((byte)category);
if ((fields & UcdFields.CanonicalCombiningClass) != 0) writer.Write((byte)canonicalCombiningClass);
if ((fields & UcdFields.BidirectionalClass) != 0) writer.Write((byte)bidirectionalClass);
- if ((fields & UcdFields.DecompositionType) != 0) writer.Write(decompositionType);
+ if ((fields & UcdFields.DecompositionMapping) != 0)
+ {
+ writer.Write((byte)characterDecompositionMapping.DecompositionType);
+ writer.Write(characterDecompositionMapping.DecompositionMapping);
+ }
if ((fields & UcdFields.NumericNumeric) != 0)
{
writer.Write(numericValue.Numerator);
diff --git a/UnicodeInformation.Builder/UnicodeDataManager.cs b/UnicodeInformation.Builder/UnicodeDataManager.cs
index d4aed13..f8dbb5e 100644
--- a/UnicodeInformation.Builder/UnicodeDataManager.cs
+++ b/UnicodeInformation.Builder/UnicodeDataManager.cs
@@ -89,7 +89,7 @@ namespace System.Unicode.Builder
throw new InvalidDataException(string.Format("Missing Bidi_Class property for code point(s) {0}.", codePoint));
}
- characterData.DecompositionType = NullIfEmpty(reader.ReadField());
+ characterData.CharacterDecompositionMapping = CharacterDecompositionMapping.Parse(NullIfEmpty(reader.ReadField()));
string numericDecimalField = NullIfEmpty(reader.ReadField());
string numericDigitField = NullIfEmpty(reader.ReadField());
diff --git a/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj b/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj
index cf70f46..00b9aa2 100644
--- a/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj
+++ b/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj
@@ -21,6 +21,7 @@
DEBUG;TRACE
prompt
4
+ true
AnyCPU
@@ -30,6 +31,7 @@
TRACE
prompt
4
+ true
true
@@ -51,6 +53,7 @@
+
diff --git a/UnicodeInformation/CompatibilityFormattingTag.cs b/UnicodeInformation/CompatibilityFormattingTag.cs
new file mode 100644
index 0000000..b19e704
--- /dev/null
+++ b/UnicodeInformation/CompatibilityFormattingTag.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace System.Unicode
+{
+ public enum CompatibilityFormattingTag : byte
+ {
+ Canonical = 0,
+ [ValueName("font"), Display(Name = "font", Description = "Font variant (for example, a blackletter form)")]
+ Font,
+ [ValueName("noBreak"), Display(Name = "noBreak", Description = "No-break version of a space or hyphen")]
+ NoBreak,
+ [ValueName("initial"), Display(Name = "initial", Description = "Initial presentation form (Arabic)")]
+ Initial,
+ [ValueName("medial"), Display(Name = "medial", Description = "Medial presentation form (Arabic)")]
+ Medial,
+ [ValueName("final"), Display(Name = "final", Description = "Final presentation form (Arabic)")]
+ Final,
+ [ValueName("isolated"), Display(Name = "isolated", Description = "Isolated presentation form (Arabic)")]
+ Isolated,
+ [ValueName("circle"), Display(Name = "circle", Description = "Encircled form")]
+ Circle,
+ [ValueName("super"), Display(Name = "super", Description = "Superscript form")]
+ Super,
+ [ValueName("sub"), Display(Name = "sub", Description = "Subscript form")]
+ Sub,
+ [ValueName("vertical"), Display(Name = "vertical", Description = "Vertical layout presentation form")]
+ Vertical,
+ [ValueName("wide"), Display(Name = "wide", Description = "Wide (or zenkaku) compatibility character")]
+ Wide,
+ [ValueName("narrow"), Display(Name = "narrow", Description = "Narrow (or hankaku) compatibility character")]
+ Narrow,
+ [ValueName("small"), Display(Name = "small", Description = "Small variant form (CNS compatibility)")]
+ Small,
+ [ValueName("square"), Display(Name = "square", Description = "CJK squared font variant")]
+ Square,
+ [ValueName("fraction"), Display(Name = "fraction", Description = "Vulgar fraction form")]
+ Fraction,
+ [ValueName("compat"), Display(Name = "compat", Description = "Otherwise unspecified compatibility character")]
+ Compat,
+ }
+}
diff --git a/UnicodeInformation/UcdFields.cs b/UnicodeInformation/UcdFields.cs
index cbe07af..da069b5 100644
--- a/UnicodeInformation/UcdFields.cs
+++ b/UnicodeInformation/UcdFields.cs
@@ -18,7 +18,7 @@ namespace System.Unicode
Category = 4,
CanonicalCombiningClass = 8,
BidirectionalClass = 16,
- DecompositionType = 32,
+ DecompositionMapping = 32,
// NumericType / NumericValue : Not exactly a bit mask here… More like [0…3] << 6
NumericDecimal = 64,
diff --git a/UnicodeInformation/UnicodeCharacterData.cs b/UnicodeInformation/UnicodeCharacterData.cs
index c6e0c9f..c99f7e9 100644
--- a/UnicodeInformation/UnicodeCharacterData.cs
+++ b/UnicodeInformation/UnicodeCharacterData.cs
@@ -14,7 +14,8 @@ namespace System.Unicode
public readonly UnicodeCategory Category;
public readonly CanonicalCombiningClass CanonicalCombiningClass;
public readonly BidirectionalClass BidirectionalClass;
- public readonly string DecompositionType;
+ public readonly CompatibilityFormattingTag DecompositionType;
+ public readonly string DecompositionMapping;
public readonly UnicodeNumericType NumericType;
private readonly UnicodeRationalNumber numericValue;
public readonly bool BidirectionalMirrored;
@@ -33,7 +34,8 @@ namespace System.Unicode
UnicodeCategory category,
CanonicalCombiningClass canonicalCombiningClass,
BidirectionalClass bidirectionalClass,
- string decompositionType,
+ CompatibilityFormattingTag decompositionType,
+ string decompositionMapping,
UnicodeNumericType numericType,
UnicodeRationalNumber numericValue,
bool bidirectionalMirrored,
@@ -51,6 +53,7 @@ namespace System.Unicode
this.CanonicalCombiningClass = canonicalCombiningClass;
this.BidirectionalClass = bidirectionalClass;
this.DecompositionType = decompositionType;
+ this.DecompositionMapping = decompositionMapping;
this.NumericType = numericType;
this.numericValue = numericValue;
this.BidirectionalMirrored = bidirectionalMirrored;
diff --git a/UnicodeInformation/UnicodeData.cs b/UnicodeInformation/UnicodeData.cs
index 528cc0e..147b165 100644
--- a/UnicodeInformation/UnicodeData.cs
+++ b/UnicodeInformation/UnicodeData.cs
@@ -64,7 +64,8 @@ namespace System.Unicode
var category = (fields & UcdFields.Category) != 0 ? (UnicodeCategory)reader.ReadByte() : UnicodeCategory.OtherNotAssigned;
var canonicalCombiningClass = (fields & UcdFields.CanonicalCombiningClass) != 0 ? (CanonicalCombiningClass)reader.ReadByte() : CanonicalCombiningClass.NotReordered;
var bidirectionalClass = (fields & UcdFields.BidirectionalClass) != 0 ? (BidirectionalClass)reader.ReadByte() : 0;
- string decompositionType = (fields & UcdFields.DecompositionType) != 0 ? reader.ReadString() : null;
+ CompatibilityFormattingTag decompositionType = (fields & UcdFields.DecompositionMapping) != 0 ? (CompatibilityFormattingTag)reader.ReadByte() : CompatibilityFormattingTag.Canonical;
+ string decompositionMapping = (fields & UcdFields.DecompositionMapping) != 0 ? reader.ReadString() : null;
var numericType = (UnicodeNumericType)((int)(fields & UcdFields.NumericNumeric) >> 6);
UnicodeRationalNumber numericValue = numericType != UnicodeNumericType.None ?
new UnicodeRationalNumber(reader.ReadInt64(), reader.ReadByte()) :
@@ -83,6 +84,7 @@ namespace System.Unicode
canonicalCombiningClass,
bidirectionalClass,
decompositionType,
+ decompositionMapping,
numericType,
numericValue,
(fields & UcdFields.BidirectionalMirrored) != 0,
diff --git a/UnicodeInformation/UnicodeInformation.csproj b/UnicodeInformation/UnicodeInformation.csproj
index 156b8d7..fbc463b 100644
--- a/UnicodeInformation/UnicodeInformation.csproj
+++ b/UnicodeInformation/UnicodeInformation.csproj
@@ -31,6 +31,7 @@
DEBUG;TRACE
prompt
4
+ false
pdbonly
@@ -56,6 +57,7 @@
+
diff --git a/UnicodeInformation/ucd.dat b/UnicodeInformation/ucd.dat
index c2eaaae..7e5dabb 100644
Binary files a/UnicodeInformation/ucd.dat and b/UnicodeInformation/ucd.dat differ