diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index d9b037b572..19c0c124db 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -59,6 +59,9 @@ + diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 6b74d18cae..b6224e4230 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -14,7 +14,7 @@ True ..\..\ICSharpCode.SharpDevelop.snk File - False + True False Auto 88080384 @@ -321,6 +321,7 @@ + diff --git a/src/Main/Base/Project/Src/Services/DisplayBinding/AutoDetectDisplayBinding.cs b/src/Main/Base/Project/Src/Services/DisplayBinding/AutoDetectDisplayBinding.cs new file mode 100644 index 0000000000..dd587a1acd --- /dev/null +++ b/src/Main/Base/Project/Src/Services/DisplayBinding/AutoDetectDisplayBinding.cs @@ -0,0 +1,84 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using ICSharpCode.SharpDevelop.Gui; + +namespace ICSharpCode.SharpDevelop +{ + /// + /// Implements content auto detection and opens the appropriate IViewContent. + /// + public sealed class AutoDetectDisplayBinding : IDisplayBinding + { + [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] + static extern unsafe int FindMimeFromData( + IntPtr pBC, + [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl, + byte* pBuffer, + int cbSize, + [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed, + int dwMimeFlags, + out IntPtr ppwzMimeOut, + int dwReserved); + + public bool IsPreferredBindingForFile(string fileName) + { + return false; + } + + public bool CanCreateContentForFile(string fileName) + { + return true; + } + + public double AutoDetectFileContent(string fileName, Stream fileContent, string detectedMimeType) + { + return double.NegativeInfinity; + } + + public IViewContent CreateContentForFile(OpenedFile file) + { + var codons = DisplayBindingService.GetCodonsPerFileName(file.FileName); + DisplayBindingDescriptor bestMatch = null; + double max = double.NegativeInfinity; + const int BUFFER_LENGTH = 4 * 1024; + + using (var stream = file.OpenRead()) { + foreach (var codon in codons) { + stream.Position = 0; + string mime = FindMimeType(new BinaryReader(stream).ReadBytes(BUFFER_LENGTH)); + stream.Position = 0; + double value = codon.Binding.AutoDetectFileContent(file.FileName, stream, mime); + if (value > max) { + max = value; + bestMatch = codon; + } + } + } + + if (bestMatch == null) + throw new InvalidOperationException(); + + return bestMatch.Binding.CreateContentForFile(file); + } + + unsafe string FindMimeType(byte[] buffer) + { + fixed (byte *b = buffer) { + const int FMFD_ENABLEMIMESNIFFING = 0x00000002; + IntPtr mimeout; + int result = FindMimeFromData(IntPtr.Zero, null, b, buffer.Length, null, FMFD_ENABLEMIMESNIFFING, out mimeout, 0); + + if (result != 0) + throw Marshal.GetExceptionForHR(result); + string mime = Marshal.PtrToStringUni(mimeout); + Marshal.FreeCoTaskMem(mimeout); + return mime; + } + } + } +} diff --git a/src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs b/src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs index cd5548f0b4..329bafd9f0 100644 --- a/src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs +++ b/src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs @@ -108,18 +108,16 @@ namespace ICSharpCode.SharpDevelop } } } - + DisplayBindingDescriptor autoDetectDescriptor = null; foreach (DisplayBindingDescriptor binding in bindings) { - if (IsPrimaryBindingValidForFileName(binding, filename) && binding.Binding.IsPreferredBindingForFile(filename)) { - return binding; + if (IsPrimaryBindingValidForFileName(binding, filename)) { + if (binding.Binding.IsPreferredBindingForFile(filename)) + return binding; + else if (binding.Binding is AutoDetectDisplayBinding) + autoDetectDescriptor = binding; } } - -// var autoDetect = new AutoDetectDisplayBinding(); -// if (autoDetect.AutoDetectFileContent(filename, new MemoryStream(File.ReadAllBytes(filename))) > double.NegativeInfinity) -// return autoDetect.BestDescriptor; - - return null; + return autoDetectDescriptor; } public static void SetDefaultCodon(string extension, DisplayBindingDescriptor bindingDescriptor) diff --git a/src/Main/Base/Project/Src/Services/DisplayBinding/IDisplayBinding.cs b/src/Main/Base/Project/Src/Services/DisplayBinding/IDisplayBinding.cs index 8a651eacbd..f2ec139568 100644 --- a/src/Main/Base/Project/Src/Services/DisplayBinding/IDisplayBinding.cs +++ b/src/Main/Base/Project/Src/Services/DisplayBinding/IDisplayBinding.cs @@ -4,7 +4,7 @@ using System; using System.IO; using System.Linq; - +using System.Runtime.InteropServices; using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.SharpDevelop @@ -39,47 +39,5 @@ namespace ICSharpCode.SharpDevelop IViewContent CreateContentForFile(OpenedFile file); } - public sealed class AutoDetectDisplayBinding : IDisplayBinding - { - DisplayBindingDescriptor bestDescriptor; - - public DisplayBindingDescriptor BestDescriptor { - get { return bestDescriptor; } - } - - public bool IsPreferredBindingForFile(string fileName) - { - return false; - } - - public bool CanCreateContentForFile(string fileName) - { - return true; - } - - public double AutoDetectFileContent(string fileName, Stream fileContent, string detectedMimeType) - { - double max = double.MinValue; - -// foreach (var codon in DisplayBindingService.GetCodonsPerFileName(fileName)) { -// double value = codon.Binding.AutoDetectFileContent(fileName, fileContent); -// if (value > max) { -// max = value; -// bestDescriptor = codon; -// } -// } -// -// fileContent.Close(); - - return max; - } - - public IViewContent CreateContentForFile(OpenedFile file) - { - if (bestDescriptor == null) - throw new InvalidOperationException(); - - return bestDescriptor.Binding.CreateContentForFile(file); - } - } + }