using System; using System.Collections.Generic; using Blacklight.Core.Keyboard; using Clave; namespace Blacklight.Core.UnitTests.Keyboard { public class ImeMessagesTests : UnitTestSharp.TestFixture { public const uint ShowCompositionWindow = 0x80000000; public static IntPtr Flags(uint flags) { return new IntPtr(unchecked((int)flags)); } /// /// Writes what it hears to one list, so the order shows. /// public class OrderedConsumer : ITextConsumer { public readonly List Heard = new List(); public bool KeyCommand(KeyboardSnapshot keyboard) { return false; } public void TextInput(string text) { Heard.Add("text " + text); } public void CompositionUpdate(string text, int caret, int targetStart, int targetEnd) { Heard.Add("composing " + text + "|" + caret + "|" + targetStart + "-" + targetEnd); } public void CompositionEnd() { Heard.Add("end"); } public void CancelKeys() { } } public class WithoutCompositionWindowTests : UnitTestSharp.TestFixture { public void ClearsOnlyTheRequestForTheCompositionWindow() { IntPtr cleared = ImeMessages.WithoutCompositionWindow(Flags(0xC000000F)); CheckEqual(0x4000000F, cleared.ToInt32()); } public void LeavesFlagsWithoutItAlone() { IntPtr cleared = ImeMessages.WithoutCompositionWindow(Flags(0x4000000F)); CheckEqual(0x4000000F, cleared.ToInt32()); } public void ItAlone_LeavesNothing() { IntPtr cleared = ImeMessages.WithoutCompositionWindow(Flags(ShowCompositionWindow)); CheckEqual(0, cleared.ToInt32()); } } public class ReportsResultTests : UnitTestSharp.TestFixture { public void CommittedText_IsTrue() { Check(ImeMessages.ReportsResult(Flags(NativeMethods.GCS_RESULTSTR))); } public void CommittedTextAlongsideACompositionString_IsTrue() { Check(ImeMessages.ReportsResult(Flags(NativeMethods.GCS_RESULTSTR | NativeMethods.GCS_COMPSTR))); } public void ACompositionStringAlone_IsFalse() { CheckFalse(ImeMessages.ReportsResult(Flags(NativeMethods.GCS_COMPSTR))); } public void NoFlags_IsFalse() { CheckFalse(ImeMessages.ReportsResult(Flags(0))); } } public class ReportsCompositionTests : UnitTestSharp.TestFixture { public void ACompositionString_IsTrue() { Check(ImeMessages.ReportsComposition(Flags(NativeMethods.GCS_COMPSTR))); } public void ACompositionStringAlongsideCommittedText_IsTrue() { Check(ImeMessages.ReportsComposition(Flags(NativeMethods.GCS_COMPSTR | NativeMethods.GCS_RESULTSTR))); } public void NoFlags_MeansItWasCleared() { Check(ImeMessages.ReportsComposition(Flags(0))); } public void CommittedTextAlone_IsFalse() { CheckFalse(ImeMessages.ReportsComposition(Flags(NativeMethods.GCS_RESULTSTR))); } public void OnlyTheCursorMoving_IsFalse() { CheckFalse(ImeMessages.ReportsComposition(Flags(NativeMethods.GCS_CURSORPOS))); } } public class TargetOfTests : UnitTestSharp.TestFixture { [UnitTestSharp.IgnoreTest] private void Of(byte[] attributes, int expectedStart, int expectedEnd) { ImeMessages.TargetOf(attributes, out int start, out int end); CheckEqual(expectedStart, start); CheckEqual(expectedEnd, end); } public void NoAttributes_HasNoTarget() { Of(null, 0, 0); } public void AnEmptyArray_HasNoTarget() { Of(new byte[0], 0, 0); } public void CharsStillBeingTyped_HaveNoTarget() { Of(new byte[] { 0, 0, 0 }, 0, 0); } public void ConvertedCharsThatAreNotTheTarget_HaveNoTarget() { Of(new byte[] { 2, 2, 5 }, 0, 0); } public void TheConvertedTargetClause_IsFound() { Of(new byte[] { 2, 2, 1, 1, 1, 2 }, 2, 5); } public void TheNotYetConvertedTargetClause_IsFound() { Of(new byte[] { 0, 3, 3, 0 }, 1, 3); } public void ATargetAtTheStart_StartsAtZero() { Of(new byte[] { 1, 1, 2 }, 0, 2); } public void ATargetAtTheEnd_EndsAtTheLength() { Of(new byte[] { 2, 1, 1 }, 1, 3); } public void OnlyTheFirstRunCounts() { Of(new byte[] { 1, 2, 1, 1 }, 0, 1); } public void AMixOfBothTargetKinds_IsOneRun() { Of(new byte[] { 1, 3, 2 }, 0, 2); } public void AnInputError_IsNotTheTarget() { Of(new byte[] { 4, 4 }, 0, 0); } } public class DeliverTests : UnitTestSharp.TestFixture { public void TheTargetClause_IsPassedOn() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "abcd", caret: 4, targetStart: 1, targetEnd: 3); CheckEqual(new[] { "composing abcd|4|1-3" }, consumer.Heard); } public void ATargetPastTheEnd_IsKeptInside() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ab", caret: 2, targetStart: 1, targetEnd: 9); CheckEqual(new[] { "composing ab|2|1-2" }, consumer.Heard); } public void ATargetStartingPastTheEnd_BecomesEmptyAtTheEnd() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ab", caret: 2, targetStart: 5, targetEnd: 9); CheckEqual(new[] { "composing ab|2|2-2" }, consumer.Heard); } public void ANegativeTargetStart_IsKeptInside() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ab", caret: 0, targetStart: -3, targetEnd: 1); CheckEqual(new[] { "composing ab|0|0-1" }, consumer.Heard); } public void AnEndBeforeTheStart_BecomesEmpty() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "abcd", caret: 0, targetStart: 3, targetEnd: 1); CheckEqual(new[] { "composing abcd|0|3-3" }, consumer.Heard); } public void CommittedTextComesBeforeTheCompositionThatFollowsIt() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: "你", composing: "ni", caret: 2); CheckEqual(new[] { "text 你", "composing ni|2|0-0" }, consumer.Heard); } public void ACommitAlone_IsJustTheText() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: "你", composing: null, caret: 0); CheckEqual(new[] { "text 你" }, consumer.Heard); } public void ACompositionAlone_IsJustTheComposition() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ni", caret: 1); CheckEqual(new[] { "composing ni|1|0-0" }, consumer.Heard); } public void AnEmptyCommit_IsLeftOut() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: "", composing: "ni", caret: 2); CheckEqual(new[] { "composing ni|2|0-0" }, consumer.Heard); } public void AnEmptyComposition_IsPassedOnSinceItSaysTheCompositionWasCleared() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "", caret: 0); CheckEqual(new[] { "composing |0|0-0" }, consumer.Heard); } public void NeitherOfThem_SaysNothing() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: null, caret: 0); CheckEqual(0, consumer.Heard.Count); } public void ACursorPastTheEnd_IsKeptInside() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ni", caret: 9); CheckEqual(new[] { "composing ni|2|0-0" }, consumer.Heard); } public void ANegativeCursor_IsKeptInside() { var consumer = new OrderedConsumer(); ImeMessages.Deliver(consumer, result: null, composing: "ni", caret: -1); CheckEqual(new[] { "composing ni|0|0-0" }, consumer.Heard); } public void WithNoConsumer_SaysNothing() { ImeMessages.Deliver(null, result: "a", composing: "b", caret: 1); } } } }