mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
274 lines
5.9 KiB
C#
274 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Xml;
|
|
|
|
namespace DataUtils
|
|
{
|
|
public class FileResXmlDoc: IDisposable
|
|
{
|
|
private string _filepath;
|
|
private XmlDocument _doc;
|
|
private bool _available;
|
|
|
|
public FileResXmlDoc (string xmlpath)
|
|
{
|
|
Create (xmlpath);
|
|
}
|
|
|
|
public bool Create (string xmlpath)
|
|
{
|
|
Destroy ();
|
|
if (string.IsNullOrEmpty (xmlpath) || !File.Exists (xmlpath))
|
|
{
|
|
_available = false;
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
_doc = new XmlDocument ();
|
|
_doc.Load (xmlpath);
|
|
_filepath = xmlpath;
|
|
_available = true;
|
|
}
|
|
catch
|
|
{
|
|
_available = false;
|
|
}
|
|
return _available;
|
|
}
|
|
|
|
public void Destroy ()
|
|
{
|
|
if (!_available) return;
|
|
_doc = null;
|
|
_available = false;
|
|
_filepath = null;
|
|
}
|
|
|
|
public void Dispose ()
|
|
{
|
|
Destroy ();
|
|
}
|
|
|
|
// Returns the chosen absolute (or resolved) path string or empty if none found
|
|
public string Get (string id)
|
|
{
|
|
if (!_available || _doc == null) return string.Empty;
|
|
if (string.IsNullOrEmpty (id)) return string.Empty;
|
|
|
|
XmlNode root = _doc.DocumentElement;
|
|
if (root == null) return string.Empty;
|
|
|
|
foreach (XmlNode node in root.ChildNodes)
|
|
{
|
|
var attr = node.Attributes? ["id"];
|
|
if (attr == null) continue;
|
|
if (!string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase)) continue;
|
|
|
|
// Build dpi -> path map
|
|
var map = new Dictionary<int, string> ();
|
|
foreach (XmlNode child in node.ChildNodes)
|
|
{
|
|
var dpiAttr = child.Attributes? ["dpi"];
|
|
string dpiStr = dpiAttr != null ? dpiAttr.Value : "default";
|
|
string text = child.InnerText ?? string.Empty;
|
|
int dpiKey = 0;
|
|
if (string.Equals (dpiStr, "default", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
dpiKey = 0;
|
|
}
|
|
else
|
|
{
|
|
int parsed;
|
|
if (int.TryParse (dpiStr, out parsed)) dpiKey = parsed;
|
|
else dpiKey = 0;
|
|
}
|
|
// Resolve relative path relative to xml file directory
|
|
string candidate = text;
|
|
if (!Path.IsPathRooted (candidate) && !string.IsNullOrEmpty (_filepath))
|
|
{
|
|
string dir = Path.GetDirectoryName (_filepath);
|
|
if (!string.IsNullOrEmpty (dir))
|
|
candidate = Path.Combine (dir, candidate);
|
|
}
|
|
// Normalize
|
|
try { candidate = Path.GetFullPath (candidate); } catch { /* ignore */ }
|
|
|
|
// Insert/overwrite by key (keep last if duplicate)
|
|
map [dpiKey] = candidate;
|
|
}
|
|
|
|
// Convert map to list and sort by string value (to mimic original)
|
|
var list = map.Select (kv => new KeyValuePair<int, string> (kv.Key, kv.Value)).ToList ();
|
|
list.Sort ((a, b) => string.CompareOrdinal (a.Value, b.Value));
|
|
|
|
// Keep only those whose file exists
|
|
var existList = new List<KeyValuePair<int, string>> ();
|
|
foreach (var kv in list)
|
|
{
|
|
if (!string.IsNullOrEmpty (kv.Value) && File.Exists (kv.Value))
|
|
existList.Add (kv);
|
|
}
|
|
|
|
int dpiPercent = UITheme.GetDPI (); // uses earlier helper
|
|
|
|
// Find first with dpi >= dpiPercent
|
|
foreach (var kv in existList)
|
|
{
|
|
if (kv.Key >= dpiPercent) return kv.Value;
|
|
}
|
|
|
|
// otherwise return first existing candidate
|
|
if (existList.Count > 0) return existList [0].Value;
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
// Overloads for convenience
|
|
//public string Get (System.String idAsString) { return Get (idAsString); }
|
|
}
|
|
public class StringResXmlDoc: IDisposable
|
|
{
|
|
private XmlDocument doc;
|
|
private bool isValid;
|
|
|
|
public bool IsValid
|
|
{
|
|
get { return isValid; }
|
|
}
|
|
|
|
public StringResXmlDoc () { }
|
|
|
|
public StringResXmlDoc (string filePath)
|
|
{
|
|
Create (filePath);
|
|
}
|
|
|
|
public bool Create (string filePath)
|
|
{
|
|
Destroy ();
|
|
|
|
if (string.IsNullOrEmpty (filePath) || !File.Exists (filePath))
|
|
return false;
|
|
|
|
try
|
|
{
|
|
doc = new XmlDocument ();
|
|
doc.Load (filePath);
|
|
isValid = true;
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
Destroy ();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Destroy ()
|
|
{
|
|
doc = null;
|
|
isValid = false;
|
|
}
|
|
|
|
public void Dispose ()
|
|
{
|
|
Destroy ();
|
|
GC.SuppressFinalize (this);
|
|
}
|
|
|
|
public string Get (string id)
|
|
{
|
|
if (!isValid || doc == null || string.IsNullOrEmpty (id))
|
|
return string.Empty;
|
|
|
|
XmlElement root = doc.DocumentElement;
|
|
if (root == null)
|
|
return string.Empty;
|
|
|
|
foreach (XmlNode node in root.ChildNodes)
|
|
{
|
|
if (node.Attributes == null)
|
|
continue;
|
|
|
|
XmlAttribute idAttr = node.Attributes ["id"];
|
|
if (idAttr == null)
|
|
continue;
|
|
|
|
if (!StringEqualsNormalized (idAttr.Value, id))
|
|
continue;
|
|
|
|
Dictionary<string, string> langValues =
|
|
new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
|
|
|
|
foreach (XmlNode sub in node.ChildNodes)
|
|
{
|
|
if (sub.Attributes == null)
|
|
continue;
|
|
|
|
XmlAttribute langAttr = sub.Attributes ["name"];
|
|
if (langAttr == null)
|
|
continue;
|
|
|
|
string lang = langAttr.Value;
|
|
if (!string.IsNullOrEmpty (lang))
|
|
{
|
|
langValues [lang] = sub.InnerText;
|
|
}
|
|
}
|
|
|
|
return GetSuitableLanguageValue (langValues);
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
public string GetString (string id) => Get (id);
|
|
|
|
public string this [string id]
|
|
{
|
|
get { return Get (id); }
|
|
}
|
|
|
|
private static bool StringEqualsNormalized (string a, string b)
|
|
{
|
|
return string.Equals (
|
|
a != null ? a.Trim () : null,
|
|
b != null ? b.Trim () : null,
|
|
StringComparison.OrdinalIgnoreCase
|
|
);
|
|
}
|
|
|
|
private static string GetSuitableLanguageValue (
|
|
Dictionary<string, string> values)
|
|
{
|
|
if (values == null || values.Count == 0)
|
|
return string.Empty;
|
|
|
|
CultureInfo culture = CultureInfo.CurrentUICulture;
|
|
string val;
|
|
|
|
if (values.TryGetValue (culture.Name, out val))
|
|
return val;
|
|
|
|
if (values.TryGetValue (culture.TwoLetterISOLanguageName, out val))
|
|
return val;
|
|
|
|
if (values.TryGetValue ("en", out val))
|
|
return val;
|
|
|
|
foreach (string v in values.Values)
|
|
return v;
|
|
|
|
return string.Empty;
|
|
}
|
|
}
|
|
}
|