public void InstallPUACharacters(string filename)
{
try
{
// 0. Intro: Prepare files
// 0.1: File names
var unidataDir = Path.Combine(IcuDir, "data");
var unicodeDataFilename = Path.Combine(IcuDir, "UnicodeDataOverrides.txt");
var originalUnicodeDataFilename = Path.Combine(unidataDir, "UnicodeDataOverrides.txt");
var nfcOverridesFileName = Path.Combine(IcuDir, "nfcOverrides.txt"); // Intermediate we will generate
var nfkcOverridesFileName = Path.Combine(IcuDir, "nfkcOverrides.txt"); // Intermediate we will generate
// 0.2: Create a one-time backup that will not be over written if the file exists
BackupOrig(unicodeDataFilename);
// 0.3: Create a stack of files to restore if we encounter and error
// This allows us to work with the original files
// If we are successful we call this.RemoveBackupFiles() to clean up
// If we are not we call this.RestoreFiles() to restore the original files
// and delete the backups
var unicodeDataBackup = CreateBackupFile(unicodeDataFilename);
AddUndoFileFrame(unicodeDataFilename, unicodeDataBackup);
//Initialize and populate the parser if necessary
// 1. Maps our XML file to a list of PUACharacter objects.
ParseCustomCharsFile(filename);
// (Step 1 has been moved before the "intro")
// 2. Sort the PUA characters
m_chars.Sort();
// 3. Open the file for reading and writing
// 4. Insert the PUA via their codepoints
InsertCharacters(m_chars.ToArray(), originalUnicodeDataFilename, unicodeDataFilename);
// 5. Generate the modified normalization file inputs.
using (var reader = new StreamReader(unicodeDataFilename, Encoding.ASCII))
{
using (var writeNfc = new StreamWriter(nfcOverridesFileName, false, Encoding.ASCII))
using (var writeNfkc = new StreamWriter(nfkcOverridesFileName, false, Encoding.ASCII))
{
reader.Peek(); // force autodetection of encoding.
try
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("Code") || line.StartsWith("block")) // header line or special instruction
continue;
// Extract the first, fourth, and sixth fields.
var match = new Regex("^([^;]*);[^;]*;[^;]*;([^;]*);[^;]*;([^;]*);").Match(line);
if (!match.Success)
continue;
string codePoint = match.Groups[1].Value.Trim();
string combiningClass = match.Groups[2].Value.Trim();
string decomp = match.Groups[3].Value.Trim();
if (!string.IsNullOrEmpty(combiningClass) && combiningClass != "0")
{
writeNfc.WriteLine(codePoint + ":" + combiningClass);
}
if (!string.IsNullOrEmpty(decomp))
{
if (decomp.StartsWith("<"))
{
int index = decomp.IndexOf(">", StringComparison.InvariantCulture);
if (index < 0)
continue; // badly formed, ignore it.
decomp = decomp.Substring(index + 1).Trim();
}
// otherwise we should arguably write to nfc.txt
// If exactly two code points write codePoint=decomp
// otherwise write codePoint>decomp
// However, we should not be modifying standard normalization.
// For now treat them all as compatibility only.
writeNfkc.WriteLine(codePoint + ">" + decomp);
}
}
}
finally
{
writeNfc.Close();
writeNfkc.Close();
reader.Close();
}
}
}
// 6. Run the "gennorm2" commands to write the actual files
RunICUTools(unidataDir, nfcOverridesFileName, nfkcOverridesFileName);
RemoveBackupFiles();
}
catch (Exception)
{
RestoreFiles();
throw;
}
finally
{
RemoveTempFiles();
}
}