diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChooseEncodingDialog.xaml b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChooseEncodingDialog.xaml index c72a7c2e38..61c5107c67 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChooseEncodingDialog.xaml +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChooseEncodingDialog.xaml @@ -13,13 +13,8 @@ Content="{core:Localize Dialog.Options.IDEOptions.TextEditor.General.FontGroupBox.FileEncodingLabel}" /> - - - - - - + DisplayMemberPath="DisplayName" + Margin="16,0,8,8" /> + /// Encoding dependency property. + /// + public static readonly DependencyProperty EncodingProperty = + DependencyProperty.Register("Encoding", typeof(Encoding), typeof(TextEditor)); + /// /// Gets/sets the encoding used when the file is saved. /// + /// + /// The method autodetects the encoding of the file and sets this property accordingly. + /// The method uses the encoding specified in this property. + /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Encoding Encoding { get; set; } + public Encoding Encoding { + get { return (Encoding)GetValue(EncodingProperty); } + set { SetValue(EncodingProperty, value); } + } /// /// Saves the text to the stream. @@ -962,8 +975,11 @@ namespace ICSharpCode.AvalonEdit { if (stream == null) throw new ArgumentNullException("stream"); - StreamWriter writer = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8); - writer.Write(this.Text); + var encoding = this.Encoding; + var document = this.Document; + StreamWriter writer = encoding != null ? new StreamWriter(stream, encoding) : new StreamWriter(stream); + if (document != null) + document.WriteTextTo(writer); writer.Flush(); // do not close the stream this.IsModified = false; diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/FileReader.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/FileReader.cs index a86442ea7b..f33369f061 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/FileReader.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/FileReader.cs @@ -36,6 +36,22 @@ namespace ICSharpCode.AvalonEdit.Utils } } + static bool IsASCIICompatible(Encoding encoding) + { + byte[] bytes = encoding.GetBytes("Az"); + return bytes.Length == 2 && bytes[0] == 'A' && bytes[1] == 'z'; + } + + static Encoding RemoveBOM(Encoding encoding) + { + switch (encoding.CodePage) { + case 65001: // UTF-8 + return UTF8NoBOM; + default: + return encoding; + } + } + /// /// Reads the content of the given stream. /// @@ -125,6 +141,8 @@ namespace ICSharpCode.AvalonEdit.Utils } } + static readonly Encoding UTF8NoBOM = new UTF8Encoding(false); + static StreamReader AutoDetect(Stream fs, byte firstByte, byte secondByte, Encoding defaultEncoding) { int max = (int)Math.Min(fs.Length, 500000); // look at max. 500 KB @@ -187,21 +205,20 @@ namespace ICSharpCode.AvalonEdit.Utils fs.Position = 0; switch (state) { case ASCII: + return new StreamReader(fs, IsASCIICompatible(defaultEncoding) ? RemoveBOM(defaultEncoding) : Encoding.ASCII); case Error: - // when the file seems to be ASCII or non-UTF8, + // When the file seems to be non-UTF8, // we read it using the user-specified encoding so it is saved again // using that encoding. if (IsUnicode(defaultEncoding)) { // the file is not Unicode, so don't read it using Unicode even if the // user has choosen Unicode as the default encoding. - // If we don't do this, SD will end up always adding a Byte Order Mark - // to ASCII files. defaultEncoding = Encoding.Default; // use system encoding instead } - return new StreamReader(fs, defaultEncoding); + return new StreamReader(fs, RemoveBOM(defaultEncoding)); default: - return new StreamReader(fs); + return new StreamReader(fs, UTF8NoBOM); } } }