From 8d6f1628b25aabbb162c533895d33147c98cb8ce Mon Sep 17 00:00:00 2001 From: BDisp Date: Wed, 12 Nov 2025 21:55:05 +0000 Subject: [PATCH] Fix IsValidLocation for wide graphemes --- Terminal.Gui/Drivers/OutputBufferImpl.cs | 7 +-- .../Drivers/DriverTests.cs | 46 ++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Terminal.Gui/Drivers/OutputBufferImpl.cs b/Terminal.Gui/Drivers/OutputBufferImpl.cs index 02237d23c..ee573789b 100644 --- a/Terminal.Gui/Drivers/OutputBufferImpl.cs +++ b/Terminal.Gui/Drivers/OutputBufferImpl.cs @@ -289,12 +289,9 @@ public class OutputBufferImpl : IOutputBuffer /// public bool IsValidLocation (string text, int col, int row) { - if (text.GetColumns () < 2) - { - return col >= 0 && row >= 0 && col < Cols && row < Rows && Clip!.Contains (col, row); - } + int textWidth = text.GetColumns (); - return Clip!.Contains (col, row) || Clip!.Contains (col + 1, row); + return col >= 0 && row >= 0 && col + textWidth <= Cols && row < Rows && Clip!.Contains (col, row); } /// diff --git a/Tests/UnitTestsParallelizable/Drivers/DriverTests.cs b/Tests/UnitTestsParallelizable/Drivers/DriverTests.cs index 9f87d80d0..ee4755507 100644 --- a/Tests/UnitTestsParallelizable/Drivers/DriverTests.cs +++ b/Tests/UnitTestsParallelizable/Drivers/DriverTests.cs @@ -1,6 +1,50 @@ using UnitTests; +using Xunit.Abstractions; namespace UnitTests_Parallelizable.DriverTests; public class DriverTests : FakeDriverBase -{ } +{ + [Theory] + [InlineData (null, true)] + [InlineData ("", true)] + [InlineData ("a", true)] + [InlineData ("👩‍❤️‍💋‍👨", false)] + public void IsValidLocation (string text, bool positive) + { + IDriver driver = CreateFakeDriver (); + driver.SetScreenSize (10, 10); + + // positive + Assert.True (driver.IsValidLocation (text, 0, 0)); + Assert.True (driver.IsValidLocation (text, 1, 1)); + Assert.Equal (positive, driver.IsValidLocation (text, driver.Cols - 1, driver.Rows - 1)); + + // negative + Assert.False (driver.IsValidLocation (text, -1, 0)); + Assert.False (driver.IsValidLocation (text, 0, -1)); + Assert.False (driver.IsValidLocation (text, -1, -1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows - 1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows - 1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows)); + + // Define a clip rectangle + driver.Clip = new (new Rectangle (5, 5, 5, 5)); + + // positive + Assert.True (driver.IsValidLocation (text, 5, 5)); + Assert.Equal (positive, driver.IsValidLocation (text, 9, 9)); + + // negative + Assert.False (driver.IsValidLocation (text, 4, 5)); + Assert.False (driver.IsValidLocation (text, 5, 4)); + Assert.False (driver.IsValidLocation (text, 10, 9)); + Assert.False (driver.IsValidLocation (text, 9, 10)); + Assert.False (driver.IsValidLocation (text, -1, 0)); + Assert.False (driver.IsValidLocation (text, 0, -1)); + Assert.False (driver.IsValidLocation (text, -1, -1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows - 1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows - 1)); + Assert.False (driver.IsValidLocation (text, driver.Cols, driver.Rows)); + } +}