diff --git a/src/XTerm.NET.Tests/OscSequenceTests.cs b/src/XTerm.NET.Tests/OscSequenceTests.cs index 3b17d4b..5ec03f8 100644 --- a/src/XTerm.NET.Tests/OscSequenceTests.cs +++ b/src/XTerm.NET.Tests/OscSequenceTests.cs @@ -127,12 +127,18 @@ public void OscHyperlink_StartLink_SetsHyperlink() { // Arrange var terminal = CreateTerminal(); + string? changedUrl = null; + var isCleared = true; + terminal.HyperlinkChanged += (sender, e) => changedUrl = e.Url; + terminal.HyperlinkChanged += (sender, e) => isCleared = e.IsCleared; // Act terminal.Write("\x1B]8;;http://example.com\x07"); // Assert Assert.Equal("http://example.com", terminal.CurrentHyperlink); + Assert.Equal("http://example.com", changedUrl); + Assert.False(isCleared); } [Fact] @@ -141,12 +147,24 @@ public void OscHyperlink_EndLink_ClearsHyperlink() // Arrange var terminal = CreateTerminal(); terminal.Write("\x1B]8;;http://example.com\x07"); + var eventCount = 0; + string changedUrl = "not cleared"; + var isCleared = false; + terminal.HyperlinkChanged += (sender, e) => + { + eventCount++; + changedUrl = e.Url; + isCleared = e.IsCleared; + }; // Act terminal.Write("\x1B]8;;\x07"); // Assert Assert.Null(terminal.CurrentHyperlink); + Assert.Equal(1, eventCount); + Assert.Equal(string.Empty, changedUrl); + Assert.True(isCleared); } [Fact] diff --git a/src/XTerm.NET/Events/TerminalEvents.cs b/src/XTerm.NET/Events/TerminalEvents.cs index 70befd0..23d577a 100644 --- a/src/XTerm.NET/Events/TerminalEvents.cs +++ b/src/XTerm.NET/Events/TerminalEvents.cs @@ -133,15 +133,29 @@ public DirectoryChangeEventArgs(string directory) } /// - /// Hyperlink event - fired when a hyperlink is encountered. + /// Hyperlink event - fired when a hyperlink is encountered or cleared. /// public class HyperlinkEventArgs : EventArgs { + /// + /// Hyperlink URL. Empty when is true. + /// public string Url { get; } + + /// + /// True when the active hyperlink was cleared. + /// + public bool IsCleared { get; } public HyperlinkEventArgs(string url) + : this(url, false) + { + } + + internal HyperlinkEventArgs(string url, bool isCleared) { Url = url; + IsCleared = isCleared; } } @@ -267,4 +281,3 @@ public CursorStyleChangedEventArgs(CursorStyle style, bool blink) } } } - diff --git a/src/XTerm.NET/InputHandler.cs b/src/XTerm.NET/InputHandler.cs index 5e2daf7..64a4631 100644 --- a/src/XTerm.NET/InputHandler.cs +++ b/src/XTerm.NET/InputHandler.cs @@ -704,6 +704,7 @@ private void HandleHyperlink(string data) // End hyperlink _terminal.CurrentHyperlink = null; _terminal.HyperlinkId = null; + _terminal.RaiseHyperlinkChanged(null); } else { @@ -722,6 +723,8 @@ private void HandleHyperlink(string data) } } } + + _terminal.RaiseHyperlinkChanged(uri); } } } diff --git a/src/XTerm.NET/Parser/EscapeSequenceParser.cs b/src/XTerm.NET/Parser/EscapeSequenceParser.cs index a4ed8e6..0c978e2 100644 --- a/src/XTerm.NET/Parser/EscapeSequenceParser.cs +++ b/src/XTerm.NET/Parser/EscapeSequenceParser.cs @@ -44,9 +44,12 @@ public class EscapeSequenceParser public event EventHandler? Osc; /// - /// Fired when DCS sequences are parsed. + /// DCS parsing is not implemented yet. This event is retained for source compatibility. /// +#pragma warning disable CS0067 + [Obsolete("DCS parsing is not implemented yet; this event is retained for source compatibility.")] public event EventHandler? Dcs; +#pragma warning restore CS0067 public EscapeSequenceParser() { diff --git a/src/XTerm.NET/Terminal.cs b/src/XTerm.NET/Terminal.cs index 97c88a7..a66ef2d 100644 --- a/src/XTerm.NET/Terminal.cs +++ b/src/XTerm.NET/Terminal.cs @@ -476,6 +476,9 @@ internal void RaiseTitleChanged(string title) => internal void RaiseDirectoryChanged(string directory) => DirectoryChanged?.Invoke(this, new TerminalEvents.DirectoryChangeEventArgs(directory)); + + internal void RaiseHyperlinkChanged(string? url) => + HyperlinkChanged?.Invoke(this, new TerminalEvents.HyperlinkEventArgs(url ?? string.Empty, url == null)); internal void RaiseWindowMoved(int x, int y) => WindowMoved?.Invoke(this, new TerminalEvents.WindowMovedEventArgs(x, y));