Skip to content

Commit

Permalink
- Fix issue #425: "No byte order mark on save" option throws stream c…
Browse files Browse the repository at this point in the history
…losed exception add unit test

- Apply dark mode to window titlebar
  • Loading branch information
lovettchris committed Oct 15, 2024
1 parent 260fe2e commit 06e7304
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
</Compile>
<Compile Include="Program.cs"></Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Win32Helpers.cs" />
<Compile Include="XmlDiffWrapper.cs" />
<EmbeddedResource Include="FormGotoLine.resx">
<DependentUpon>FormGotoLine.cs</DependentUpon>
Expand Down
24 changes: 24 additions & 0 deletions src/Application/FormMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1753,13 +1753,37 @@ protected virtual void OnSettingsChanged(object sender, string name)
this._analytics.SetEnabled(this._settings.GetBoolean("AllowAnalytics", false));
}
break;
case "Theme":
OnThemeChanged();
break;
}

this._delayedActions.StartDelayedAction("DelaySaveSettings",
() => SaveSettings(new CancelEventArgs()),
TimeSpan.FromSeconds(1));
}

private void OnThemeChanged()
{
if ((ColorTheme)this._settings["Theme"] == ColorTheme.Light)
{
ThemeAllControls(this, false);
}
else
{
ThemeAllControls(this, true);
}
}

private void ThemeAllControls(Control parent, bool darkMode)
{
Win32Helpers.UseImmersiveDarkMode(this.Handle, darkMode);
foreach (Control control in parent.Controls)
{
ThemeAllControls(control, darkMode);
}
}

public void SaveErrors(string filename)
{
this._taskList.Save(filename);
Expand Down
67 changes: 67 additions & 0 deletions src/Application/Win32Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Runtime.InteropServices;

namespace XmlNotepad
{
internal enum DWMWINDOWATTRIBUTE : uint
{
DWMWA_NCRENDERING_ENABLED,
DWMWA_NCRENDERING_POLICY,
DWMWA_TRANSITIONS_FORCEDISABLED,
DWMWA_ALLOW_NCPAINT,
DWMWA_CAPTION_BUTTON_BOUNDS,
DWMWA_NONCLIENT_RTL_LAYOUT,
DWMWA_FORCE_ICONIC_REPRESENTATION,
DWMWA_FLIP3D_POLICY,
DWMWA_EXTENDED_FRAME_BOUNDS,
DWMWA_HAS_ICONIC_BITMAP,
DWMWA_DISALLOW_PEEK,
DWMWA_EXCLUDED_FROM_PEEK,
DWMWA_CLOAK,
DWMWA_CLOAKED,
DWMWA_FREEZE_REPRESENTATION,
DWMWA_PASSIVE_UPDATE_MODE,
DWMWA_USE_HOSTBACKDROPBRUSH,
DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,
DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
DWMWA_WINDOW_CORNER_PREFERENCE = 33,
DWMWA_BORDER_COLOR,
DWMWA_CAPTION_COLOR,
DWMWA_TEXT_COLOR,
DWMWA_VISIBLE_FRAME_BORDER_THICKNESS,
DWMWA_SYSTEMBACKDROP_TYPE,
DWMWA_LAST
};


internal static class Win32Helpers
{
[DllImport("Dwmapi")]
static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute, ref int attrValue, uint cbAttribute);

internal static bool UseImmersiveDarkMode(IntPtr handle, bool enabled)
{
if (IsWindows10OrGreater(17763))
{
var attribute = DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
if (IsWindows10OrGreater(18985))
{
attribute = DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE;
}

int useImmersiveDarkMode = enabled ? 1 : 0;
return DwmSetWindowAttribute(handle, attribute,
ref useImmersiveDarkMode, sizeof(int)) == 0;
}

return false;
}

private static bool IsWindows10OrGreater(int build = -1)
{
return Environment.OSVersion.Version.Major >= 10 &&
Environment.OSVersion.Version.Build >= build;
}

}
}
9 changes: 5 additions & 4 deletions src/Model/XmlCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ public void SaveCopy(string filename)
Settings settings = (Settings)this._site.GetService(typeof(Settings));
if (settings != null)
{
noBom = (bool)settings["NoByteOrderMark"];
noBom = settings.GetBoolean("NoByteOrderMark", false);
if (noBom)
{
// then we must have an XML declaration with an encoding attribute.
Expand All @@ -414,10 +414,11 @@ public void SaveCopy(string filename)
EncodingHelpers.InitializeWriterSettings(w, this._site);
_doc.Save(w);
}
ms.Seek(0, SeekOrigin.Begin);

EncodingHelpers.WriteFileWithoutBOM(ms, filename);

using (var stm = new MemoryStream(ms.ToArray()))
{
EncodingHelpers.WriteFileWithoutBOM(stm, filename);
}
}
else
{
Expand Down
39 changes: 39 additions & 0 deletions src/UnitTests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3099,9 +3099,48 @@ public void TestChangeTo()
this.SaveAndCompare("out.xml", "test8.xml");
}

[TestMethod]
[Timeout(TestMethodTimeout)]
public void TestNoByteOrderMark()
{
SetNoByteOrderMark(true);
Trace.WriteLine("TestNoByteOrderMark==========================================================");
string testFile = _testDir + "UnitTests\\test8.xml";
var w = this.LaunchNotepad(testFile);
Sleep(1000);
string outFile = Save("out.xml");

AssertUtf8Bom(testFile, true);
AssertUtf8Bom(outFile, false);

// test we can load it
XmlDocument doc = new XmlDocument();
doc.Load(outFile);
}

//==================================================================================

void SetNoByteOrderMark(bool value)
{
this.testSettings["NoByteOrderMark"] = value;
this.testSettings.Save(this.testSettings.FileName);
}

private void AssertUtf8Bom(string filename, bool expected)
{
var data = File.ReadAllBytes(filename);
bool isUtf8 = data.Length > 3 && data[0] == 0xef && data[1] == 0xBB && data[2] == 0xBF;
if (isUtf8 && !expected)
{
throw new ApplicationException("Byte order mark is present in {filename} but should not be");
}
else if (!isUtf8 && expected)
{
throw new ApplicationException("Byte order mark is not present in {filename} but should be");
}
}


private void SaveAndCompare(string outname, string compareWith)
{
string outFile = Save(outname);
Expand Down
4 changes: 4 additions & 0 deletions src/Updates/Updates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<history>https://github.com/microsoft/XmlNotepad/blob/master/src/Updates/Updates.xml</history>
<frequency>1.00:00:00</frequency>
</application>
<version number="2.9.0.15">
<bug>Fix issue #425: "No byte order mark on save" option throws stream closed exception add unit test.</bug>
<bug>Apply dark mode to window titlebar.</bug>
</version>
<version number="2.9.0.14">
<bug>Fix issue #418: check setttings-file for "read-only".</bug>
<bug>Fix issue #398: XmlNotepad detects xml-errors at empty nillable xsd:date Elements, but xml is correct</bug>
Expand Down
2 changes: 2 additions & 0 deletions src/Version/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@
// Build Number
// Revision
//
// This is the Master version number from which UpdateVersions will propagate to
// Package.appxmanifest, Product.wxs, Bundle.wxs and Application.csproj.
[assembly: AssemblyVersion("2.9.0.14")]
[assembly: AssemblyFileVersion("2.9.0.14")]

0 comments on commit 06e7304

Please sign in to comment.