Explorar o código

Merge branch 'v2_develop' into v2_4239-Charmap

Tig hai 1 día
pai
achega
2db6bc18e0

+ 2 - 2
Examples/NativeAot/Publish_linux-x64_Debug.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Debug
+dotnet build -c Debug
 dotnet publish -c Debug -r linux-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_linux-x64_Release.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Release
+dotnet build -c Release
 dotnet publish -c Release -r linux-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_osx-x64_Debug.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Debug
+dotnet build -c Debug
 dotnet publish -c Debug -r osx-x64 --self-contained

+ 2 - 2
Examples/NativeAot/Publish_osx-x64_Release.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
 
-dotnet clean
-dotnet build
+dotnet clean -c Release
+dotnet build -c Release
 dotnet publish -c Release -r osx-x64 --self-contained

+ 27 - 5
Terminal.Gui/Configuration/DeepCloner.cs

@@ -278,17 +278,37 @@ public static class DeepCloner
 
         // Determine dictionary type and comparer
         Type [] genericArgs = type.GetGenericArguments ();
-        Type dictType = genericArgs.Length == 2
-            ? typeof (Dictionary<,>).MakeGenericType (genericArgs)
-            : typeof (Dictionary<object, object>);
+        Type dictType;
+
+        if (genericArgs.Length == 2)
+        {
+            if (type.GetGenericTypeDefinition () == typeof (Dictionary<,>))
+            {
+                dictType = typeof (Dictionary<,>).MakeGenericType (genericArgs);
+            }
+            else if (type.GetGenericTypeDefinition () == typeof (ConcurrentDictionary<,>))
+            {
+                dictType = typeof (ConcurrentDictionary<,>).MakeGenericType (genericArgs);
+            }
+            else
+            {
+                throw new InvalidOperationException (
+                                                     $"Unsupported dictionary type: {type}. Only Dictionary<,> and ConcurrentDictionary<,> are supported.");
+            }
+        }
+        else
+        {
+            dictType = typeof (Dictionary<object, object>);
+        }
+
         object? comparer = type.GetProperty ("Comparer")?.GetValue (source);
 
         // Create a temporary dictionary to hold cloned key-value pairs
         IDictionary tempDict = CreateDictionaryInstance (dictType, comparer);
         visited.TryAdd (source, tempDict);
 
-
         object? lastKey = null;
+
         try
         {
             // Clone all key-value pairs
@@ -311,7 +331,9 @@ public static class DeepCloner
         catch (InvalidOperationException ex)
         {
             // Handle cases where the dictionary is modified during enumeration
-            throw new InvalidOperationException ($"Error cloning dictionary ({source}) (last key was \"{lastKey}\"). Ensure the source dictionary is not modified during cloning.", ex);
+            throw new InvalidOperationException (
+                                                 $"Error cloning dictionary ({source}) (last key was \"{lastKey}\"). Ensure the source dictionary is not modified during cloning.",
+                                                 ex);
         }
 
         // If the original dictionary type has a parameterless constructor, create a new instance

+ 11 - 7
Terminal.Gui/Drivers/CursesDriver/CursesDriver.cs

@@ -536,6 +536,8 @@ internal class CursesDriver : ConsoleDriver
         return true;
     }
 
+    private EscSeqUtils.DECSCUSR_Style? _currentDecscusrStyle;
+
     /// <inheritdoc/>
     public override bool SetCursorVisibility (CursorVisibility visibility)
     {
@@ -547,17 +549,19 @@ internal class CursesDriver : ConsoleDriver
         if (!RunningUnitTests)
         {
             Curses.curs_set (((int)visibility >> 16) & 0x000000FF);
+            Curses.leaveok (_window!.Handle, !Force16Colors);
         }
 
         if (visibility != CursorVisibility.Invisible)
         {
-            _mainLoopDriver?.WriteRaw (
-                                       EscSeqUtils.CSI_SetCursorStyle (
-                                                                       (EscSeqUtils.DECSCUSR_Style)
-                                                                       (((int)visibility >> 24)
-                                                                        & 0xFF)
-                                                                      )
-                                      );
+            if (_currentDecscusrStyle is null || _currentDecscusrStyle != (EscSeqUtils.DECSCUSR_Style)(((int)visibility >> 24) & 0xFF))
+            {
+                _currentDecscusrStyle = (EscSeqUtils.DECSCUSR_Style)(((int)visibility >> 24) & 0xFF);
+
+                _mainLoopDriver?.WriteRaw (
+                                           EscSeqUtils.CSI_SetCursorStyle ((EscSeqUtils.DECSCUSR_Style)_currentDecscusrStyle)
+                                          );
+            }
         }
 
         _currentCursorVisibility = visibility;

+ 1 - 2
Terminal.Gui/Drivers/CursesDriver/UnixMainLoop.cs

@@ -249,8 +249,7 @@ internal class UnixMainLoop : IMainLoopDriver
 
     private class Watch
     {
-        // BUGBUG: Fix this nullable issue.
-        public Func<MainLoop, bool> Callback;
+        public Func<MainLoop, bool>? Callback;
         public Condition Condition;
         public int File;
     }

+ 1 - 1
Terminal.Gui/ViewBase/ViewCollectionHelpers.cs

@@ -10,7 +10,7 @@ internal static class ViewCollectionHelpers
             // The list parameter might be the live `_subviews`, so freeze it under a lock
             lock (list)
             {
-                return [.. list]; // C# 12 slice copy (= new List<View>(list).ToArray())
+                return list.ToArray (); // It’s slightly less “fancy C# 12”, but much safer in multithreaded code
             }
         }
 

+ 87 - 0
Tests/UnitTestsParallelizable/Configuration/DeepClonerTests.cs

@@ -551,4 +551,91 @@ public class DeepClonerTests
         Assert.True (stopwatch.ElapsedMilliseconds < 1000); // Ensure it completes within 1 second
     }
 
+    [Fact]
+    public void CloneDictionary_ShouldClone_NormalDictionary ()
+    {
+        // Arrange: A supported generic dictionary
+        var original = new Dictionary<string, int>
+        {
+            ["one"] = 1,
+            ["two"] = 2,
+            ["three"] = 3
+        };
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotNull (cloned);
+        Assert.NotSame (original, cloned); // must be a new instance
+        Assert.Equal (original, cloned);   // must have same contents
+        Assert.Equal (original.Count, cloned.Count);
+        Assert.Equal (original ["one"], cloned ["one"]);
+        Assert.Equal (original ["two"], cloned ["two"]);
+        Assert.Equal (original ["three"], cloned ["three"]);
+    }
+
+    [Fact]
+    public void CloneDictionary_ShouldClone_ConcurrentDictionary ()
+    {
+        // Arrange
+        var original = new ConcurrentDictionary<string, string>
+        {
+            ["a"] = "alpha",
+            ["b"] = "beta"
+        };
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Equal (original, cloned);
+    }
+
+    [Fact]
+    public void CloneDictionary_Empty_Dictionary_ShouldWork ()
+    {
+        // Arrange
+        var original = new Dictionary<int, string> ();
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Empty (cloned!);
+    }
+
+    [Fact]
+    public void CloneDictionary_Empty_ConcurrentDictionary_ShouldWork ()
+    {
+        // Arrange
+        var original = new ConcurrentDictionary<int, string> ();
+
+        // Act
+        var cloned = DeepCloner.DeepClone (original);
+
+        // Assert
+        Assert.NotSame (original, cloned);
+        Assert.Empty (cloned!);
+    }
+
+    [Fact]
+    public void CloneDictionary_With_Unsupported_Dictionary_Throws ()
+    {
+        // Arrange: A generic dictionary type (SortedDictionary for example)
+        var unsupportedDict = new SortedDictionary<int, string>
+        {
+            { 1, "A" },
+            { 2, "B" }
+        };
+
+        // Act & Assert: DeepCloner should throw
+        Assert.ThrowsAny<InvalidOperationException> (() =>
+                                                     {
+                                                         // This should throw, because DeepCloner does not support SortedDictionary
+                                                         _ = DeepCloner.DeepClone (unsupportedDict);
+                                                     });
+    }
 }

BIN=BIN
local_packages/Terminal.Gui.2.0.0.nupkg


BIN=BIN
local_packages/Terminal.Gui.2.0.0.snupkg