diff --git a/BurnOutSharp/External/libgsf/GsfBlob.cs b/BurnOutSharp/External/libgsf/GsfBlob.cs index 966da23f..852f0b6c 100644 --- a/BurnOutSharp/External/libgsf/GsfBlob.cs +++ b/BurnOutSharp/External/libgsf/GsfBlob.cs @@ -23,6 +23,7 @@ using System; namespace LibGSF { + // TODO: Can this be made internal? public class GsfBlob { #region Properties @@ -54,6 +55,8 @@ namespace LibGSF { if (!((size > 0 && data_to_copy != null) || (size == 0 && data_to_copy == null))) return null; + if (error != null) + return null; byte[] data; if (data_to_copy != null) diff --git a/BurnOutSharp/External/libgsf/GsfClipData.cs b/BurnOutSharp/External/libgsf/GsfClipData.cs index c60fc935..c557c448 100644 --- a/BurnOutSharp/External/libgsf/GsfClipData.cs +++ b/BurnOutSharp/External/libgsf/GsfClipData.cs @@ -27,6 +27,7 @@ namespace LibGSF { #region Enums + // TODO: Can this be made internal? public enum GsfClipFormat { /// @@ -66,6 +67,7 @@ namespace LibGSF GSF_CLIP_FORMAT_UNKNOWN } + // TODO: Can this be made internal? public enum GsfClipFormatWindows { /// @@ -96,6 +98,7 @@ namespace LibGSF #endregion + // TODO: Can this be made internal? public class GsfClipData { #region Properties @@ -156,16 +159,12 @@ namespace LibGSF /// A GsfClipFormatWindows value. public GsfClipFormatWindows GetWindowsClipboardFormat(ref Exception error) { - GsfClipFormatWindows format; - if (error == null) return GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ERROR; - if (Format != GsfClipFormat.GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD) return GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ERROR; long size = DataBlob.Size; - if (size < 4) { error = new InvalidDataException("The clip_data is in Windows clipboard format, but it is smaller than the required 4 bytes."); @@ -173,30 +172,23 @@ namespace LibGSF } byte[] data = DataBlob.Data; - uint value = GSF_LE_GET_GUINT32(data, 0); switch (value) { case (uint)GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_METAFILE: - format = CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_METAFILE, "Windows Metafile format", size, ref error); - break; + return CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_METAFILE, "Windows Metafile format", size, ref error); case (uint)GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_DIB: case 2: /* CF_BITMAP */ - format = CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_DIB, "Windows DIB or BITMAP format", size, ref error); - break; + return CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_DIB, "Windows DIB or BITMAP format", size, ref error); case (uint)GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE: - format = CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE, "Windows Enhanced Metafile format", size, ref error); - break; + return CheckFormatWindows(GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE, "Windows Enhanced Metafile format", size, ref error); default: - format = GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_UNKNOWN; - break; + return GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_UNKNOWN; } - - return format; } /// @@ -227,7 +219,7 @@ namespace LibGSF if (win_format == GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ERROR) return null; - // gsf_clip_data_get_windows_clipboard_format() already did the size checks for us, + // GetWindowsClipboardFormat() already did the size checks for us, // so we can jump to the offset right away without doing extra checks. offset = GetWindowsClipboardDataOffset(win_format); @@ -241,6 +233,10 @@ namespace LibGSF return new ReadOnlySpan(data, (int)offset, (int)ret_size).ToArray(); } + #endregion + + #region Utilities + private static void SetErrorMissingClipboardData(ref Exception error, string format_name, long at_least_size) { error = new InvalidDataException($"The clip_data is in {format_name}, but it is smaller than at least {at_least_size} bytes"); @@ -257,11 +253,9 @@ namespace LibGSF // FIXME: does this have a PACKEDMETA in front as well, similar to GSF_CLIP_FORMAT_WINDOWS_METAFILE? new FormatOffsetPair { Format = GsfClipFormatWindows.GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE, Offset = 4 } }; + int num_pairs = pairs.Length; - - int i; - - for (i = 0; i < num_pairs; i++) + for (int i = 0; i < num_pairs; i++) { if (pairs[i].Format == format) return pairs[i].Offset; diff --git a/BurnOutSharp/External/libgsf/GsfDocMetaData.cs b/BurnOutSharp/External/libgsf/GsfDocMetaData.cs index 44fbad5a..834b951c 100644 --- a/BurnOutSharp/External/libgsf/GsfDocMetaData.cs +++ b/BurnOutSharp/External/libgsf/GsfDocMetaData.cs @@ -31,6 +31,7 @@ using static LibGSF.GsfUtils; namespace LibGSF { + // TODO: Can this be made internal? public class GsfDocProp { #region Properties @@ -40,7 +41,7 @@ namespace LibGSF public object Value { get; set; } /// - /// Optionally NULL + /// Optionally null /// public string LinkedTo { get; set; } @@ -104,9 +105,29 @@ namespace LibGSF return old_val; } + /// + /// A debugging utility to dump prop as text via Console + /// + /// New in 1.14.2 + public void Dump() + { + if (Value is List va) + { + for (int i = 0; i < va.Count; i++) + { + Console.WriteLine($"\t[{i}] = Name: {va[i].Name}, Value: {va[i].Value}, Link: {va[i].LinkedTo}, Ref: {va[i].RefCount}"); + } + } + else + { + Console.WriteLine($"\t= {Value}"); + } + } + #endregion } + // TODO: Can this be made internal? public class GsfDocMetaData { #region Properties @@ -122,9 +143,7 @@ namespace LibGSF /// private GsfDocMetaData() { } - /// - /// A new metadata property collection - /// + /// A new metadata property collection public static GsfDocMetaData Create() => new GsfDocMetaData(); #endregion @@ -164,6 +183,84 @@ namespace LibGSF Table[name] = docProp; } + /// + /// If does not exist in the collection, do nothing. If @name does exist, + /// remove it and its value from the collection + /// + /// The non-null string name of the property + public void Remove(string name) + { + if (name == null) + return; + + if (!Table.ContainsKey(name)) + return; + + Table.Remove(name); + } + + /// The property with in meta. + public GsfDocProp Steal(string name) + { + if (name == null) + return null; + + if (!Table.ContainsKey(name)) + return null; + + GsfDocProp prop = Table[name]; + if (prop != null) + Table.Remove(name); + + return prop; + } + + public void Store(GsfDocProp prop) + { + if (prop == null) + return; + + if (prop != Lookup(prop.Name)) + return; + + Table[prop.Name] = prop; + } + + /// + /// Iterate through each (key, value) pair in this collection + /// + /// The function called once for each element in the collection + /// Any supplied user data + public void ForEach(Action func, object user_data) + { + if (Table.Count == 0) + return; + + // Sort the pairs by property name in order to generate consistent files + List> pairs = Table.ToList(); + pairs.Sort((a, b) => DerefStrcmp(a.Key, b.Key)); + + for (int i = 0; i < pairs.Count; i++) + { + func(pairs[i].Key, pairs[i].Value, user_data); + } + } + + /// The number of items in this collection + public int Size() => Table.Count; + + /// + /// A debugging utility to dump the content of meta via Console + /// + public void Dump() + { + ForEach(PrintProperty, null); + } + + #endregion + + #region MS-OLE + /// /// Read a stream formated as a set of MS OLE properties from and store the /// results in . @@ -361,52 +458,6 @@ namespace LibGSF return null; } - /// - /// If does not exist in the collection, do nothing. If @name does exist, - /// remove it and its value from the collection - /// - /// The non-null string name of the property - public void Remove(string name) - { - if (name == null) - return; - - if (!Table.ContainsKey(name)) - return; - - Table.Remove(name); - } - - /// The property with in meta. - public GsfDocProp Steal(string name) - { - if (name == null) - return null; - - if (!Table.ContainsKey(name)) - return null; - - GsfDocProp prop = Table[name]; - if (prop != null) - Table.Remove(name); - - return prop; - } - - public void Store(GsfDocProp prop) - { - if (prop == null) - return; - - if (Table.ContainsKey(prop.Name) && Table[prop.Name] == prop) - return; - - Table[prop.Name] = prop; - } - - /// The number of items in this collection - public int Size() => Table.Count; - /// /// A kludge to differentiate DocumentSummary from Summary /// True on success @@ -539,6 +590,18 @@ namespace LibGSF #region Utilities + private static int DerefStrcmp(string a, string b) => a.CompareTo(b); + + private static void PrintProperty(string name, GsfDocProp prop, object user_data) + { + if (prop.LinkedTo != null) + Console.WriteLine($"prop '{name}' LINKED TO -> {prop.LinkedTo}"); + else + Console.WriteLine($"prop '{name}'"); + + prop.Dump(); + } + private int CodePageCharSize(int codepage) => (codepage == 1200 || codepage == 1201 ? 2 : 1); private static int PropertyCompare(GsfMSOleMetaDataProp prop_a, GsfMSOleMetaDataProp prop_b)