space-wizards / RobustToolbox

Robust multiplayer game engine, used by Space Station 14
https://spacestation14.io
Other
536 stars 394 forks source link

Exception when TextEdit placeholder text spans multiple lines #4953

Closed 0x6273 closed 6 months ago

0x6273 commented 6 months ago

If a TextEdit placeholder spans multiple lines, it is possible to put the cursor on different lines. On release it's not possible to type except when the cursor is on the first line, and attempting to do so on debug throws this exception:

Unhandled exception. System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
   at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at Robust.Shared.Utility.Rope.Split(Node rope, Int64 index) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Shared/Utility/TextRope.cs:line 362
   at Robust.Shared.Utility.Rope.ReplaceSubstring(Node rope, Int64 start, Int64 length, String text) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Shared/Utility/TextRope.cs:line 396
   at Robust.Client.UserInterface.Controls.TextEdit.InsertAtCursor(String text) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/UserInterface/Controls/TextEdit.cs:line 855
   at Robust.Client.UserInterface.Controls.TextEdit.TextEntered(GUITextEnteredEventArgs args) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/UserInterface/Controls/TextEdit.cs:line 730
   at Robust.Client.UserInterface.UserInterfaceManager.TextEntered(TextEnteredEventArgs textEnteredEvent) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/UserInterface/UserInterfaceManager.Input.cs:line 233
   at Robust.Client.GameController.TextEntered(TextEnteredEventArgs textEnteredEvent) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.Input.cs:line 25
   at Robust.Client.Graphics.Clyde.Clyde.DispatchSingleEvent(DEventBase ev) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/Graphics/Clyde/Clyde.Events.cs:line 62
   at Robust.Client.Graphics.Clyde.Clyde.DispatchEvents() in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/Graphics/Clyde/Clyde.Events.cs:line 31
   at Robust.Client.Graphics.Clyde.Clyde.ProcessInput(FrameEventArgs frameEventArgs) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs:line 392
   at Robust.Client.GameController.Input(FrameEventArgs frameEventArgs) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.cs:line 489
   at Robust.Client.GameController.<StartupContinue>b__58_2(Object sender, FrameEventArgs args) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.cs:line 240
   at Robust.Shared.Timing.GameLoop.Run() in /home/user/Projects/space-station-14/RobustToolbox/Robust.Shared/Timing/GameLoop.cs:line 187
   at Robust.Client.GameController.ContinueStartupAndLoop(DisplayMode mode) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.Standalone.cs:line 162
   at Robust.Client.GameController.GameThreadMain(DisplayMode mode) in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.Standalone.cs:line 147
   at Robust.Client.GameController.<>c__DisplayClass100_0.<Run>b__0() in /home/user/Projects/space-station-14/RobustToolbox/Robust.Client/GameController/GameController.Standalone.cs:line 106

I encountered this while developing for a downstream fork. I don't think a multi line placeholder text is present in content currently.

Repro:

0x6273 commented 6 months ago

It looks like there is code that's supposed to clamp CursorPosition here: https://github.com/space-wizards/RobustToolbox/blob/c12971cb9bc3b58de831e3418b4d06874620cc0b/Robust.Client/UserInterface/Controls/TextEdit.cs#L120-L122

But it looks like it never actually gets clamped because the code that handles clicking and arrow keys sets the field directly, bypassing the property setter.