From 365fcf24c3ca366bb6422f24546f07a6b0cc649e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 24 Feb 2023 01:11:13 +0200 Subject: [PATCH] Implement #19468 and rename functions cursor to caret --- src/openrct2-ui/TextComposition.cpp | 221 ++++++++++++++++++++++------ src/openrct2-ui/TextComposition.h | 10 +- src/openrct2/interface/Chat.cpp | 2 +- 3 files changed, 185 insertions(+), 48 deletions(-) diff --git a/src/openrct2-ui/TextComposition.cpp b/src/openrct2-ui/TextComposition.cpp index 80f0efbd11..66184cb926 100644 --- a/src/openrct2-ui/TextComposition.cpp +++ b/src/openrct2-ui/TextComposition.cpp @@ -118,14 +118,6 @@ void TextComposition::HandleMessage(const SDL_Event* e) break; } - // Clear the input on Backspace (Windows/Linux) or Backspace (macOS) - if (key == SDLK_BACKSPACE && (modifier & KEYBOARD_PRIMARY_MODIFIER)) - { - Clear(); - console.RefreshCaret(_session.SelectionStart); - WindowUpdateTextbox(); - } - switch (key) { case SDLK_BACKSPACE: @@ -133,7 +125,10 @@ void TextComposition::HandleMessage(const SDL_Event* e) if (_session.SelectionStart > 0) { size_t endOffset = _session.SelectionStart; - CursorLeft(); + if (modifier & KEYBOARD_PRIMARY_MODIFIER) + CaretMoveToLeftToken(); + else + CaretMoveLeft(); _session.SelectionSize = endOffset - _session.SelectionStart; Delete(); @@ -142,17 +137,20 @@ void TextComposition::HandleMessage(const SDL_Event* e) } break; case SDLK_HOME: - CursorHome(); + CaretMoveToStart(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_END: - CursorEnd(); + CaretMoveToEnd(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_DELETE: { size_t startOffset = _session.SelectionStart; - CursorRight(); + if (modifier & KEYBOARD_PRIMARY_MODIFIER) + CaretMoveToRightToken(); + else + CaretMoveRight(); _session.SelectionSize = _session.SelectionStart - startOffset; _session.SelectionStart = startOffset; Delete(); @@ -164,11 +162,17 @@ void TextComposition::HandleMessage(const SDL_Event* e) WindowCancelTextbox(); break; case SDLK_LEFT: - CursorLeft(); + if (modifier & KEYBOARD_PRIMARY_MODIFIER) + CaretMoveToLeftToken(); + else + CaretMoveLeft(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_RIGHT: - CursorRight(); + if (modifier & KEYBOARD_PRIMARY_MODIFIER) + CaretMoveToRightToken(); + else + CaretMoveRight(); console.RefreshCaret(_session.SelectionStart); break; case SDLK_c: @@ -192,12 +196,12 @@ void TextComposition::HandleMessage(const SDL_Event* e) } } -void TextComposition::CursorHome() +void TextComposition::CaretMoveToStart() { _session.SelectionStart = 0; } -void TextComposition::CursorEnd() +void TextComposition::CaretMoveToEnd() { size_t selectionOffset = _session.Buffer->size(); const utf8* ch = _session.Buffer->c_str() + _session.SelectionStart; @@ -210,38 +214,166 @@ void TextComposition::CursorEnd() _session.SelectionStart = selectionOffset; } -void TextComposition::CursorLeft() +void TextComposition::CaretMoveLeft() { size_t selectionOffset = _session.SelectionStart; - if (selectionOffset > 0) - { - const utf8* ch = _session.Buffer->c_str() + selectionOffset; - do - { - ch--; - selectionOffset--; - } while (!UTF8IsCodepointStart(ch) && selectionOffset > 0); + if (selectionOffset == 0) + return; - _session.SelectionStart = selectionOffset; - } + const utf8* ch = _session.Buffer->c_str() + selectionOffset; + do + { + ch--; + selectionOffset--; + } while (!UTF8IsCodepointStart(ch) && selectionOffset > 0); + + _session.SelectionStart = selectionOffset; } -void TextComposition::CursorRight() +void TextComposition::CaretMoveRight() { size_t selectionOffset = _session.SelectionStart; size_t selectionMaxOffset = _session.Buffer->size(); - if (selectionOffset < selectionMaxOffset) - { - const utf8* ch = _session.Buffer->c_str() + _session.SelectionStart; - do - { - ch++; - selectionOffset++; - } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + if (selectionOffset >= selectionMaxOffset) + return; - _session.SelectionSize = std::max(0, _session.SelectionSize - (selectionOffset - _session.SelectionStart)); - _session.SelectionStart = selectionOffset; + const utf8* ch = _session.Buffer->c_str() + _session.SelectionStart; + do + { + ch++; + selectionOffset++; + } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + + _session.SelectionSize = std::max(0, _session.SelectionSize - (selectionOffset - _session.SelectionStart)); + _session.SelectionStart = selectionOffset; +} + +static bool isWhitespace(uint32_t cp) +{ + return cp == ' ' || cp == '\t'; +} + +void TextComposition::CaretMoveToLeftToken() +{ + if (_session.SelectionStart == 0) + return; + + size_t selectionOffset = _session.SelectionStart - 1; + size_t lastChar = selectionOffset; + + const utf8* ch = _session.Buffer->c_str() + selectionOffset; + + // Read until first non-whitespace. + while (selectionOffset > 0) + { + while (!UTF8IsCodepointStart(ch) && selectionOffset > 0) + { + ch--; + selectionOffset--; + } + + auto cp = UTF8GetNext(ch, nullptr); + if (!isWhitespace(cp)) + { + lastChar = selectionOffset; + break; + } + + ch--; + selectionOffset--; } + + // Skip white spaces. + while (selectionOffset > 0) + { + while (!UTF8IsCodepointStart(ch) && selectionOffset > 0) + { + ch--; + selectionOffset--; + } + + auto cp = UTF8GetNext(ch, nullptr); + if (isWhitespace(cp)) + break; + + lastChar = selectionOffset; + + ch--; + selectionOffset--; + } + + _session.SelectionSize = std::max(0, _session.SelectionSize - (selectionOffset - _session.SelectionStart)); + _session.SelectionStart = selectionOffset == 0 ? 0 : lastChar; +} + +void TextComposition::CaretMoveToRightToken() +{ + size_t selectionOffset = _session.SelectionStart; + size_t selectionMaxOffset = _session.Buffer->size(); + + if (selectionOffset >= selectionMaxOffset) + return; + + const utf8* ch = _session.Buffer->c_str() + selectionOffset; + + // Find a valid codepoint start. + while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset) + { + ch++; + selectionOffset++; + } + auto cp = UTF8GetNext(ch, nullptr); + + if (isWhitespace(cp)) + { + // Read until first non-whitespace. + while (selectionOffset < selectionMaxOffset) + { + do + { + ch++; + selectionOffset++; + } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + + cp = UTF8GetNext(ch, nullptr); + if (!isWhitespace(cp)) + break; + } + } + else + { + // Read until first non-whitespace. + while (selectionOffset < selectionMaxOffset) + { + do + { + ch++; + selectionOffset++; + } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + + cp = UTF8GetNext(ch, nullptr); + if (isWhitespace(cp)) + break; + } + + // Skip white spaces. + while (selectionOffset < selectionMaxOffset) + { + // Read until first non-whitespace. + do + { + ch++; + selectionOffset++; + } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + + cp = UTF8GetNext(ch, nullptr); + if (!isWhitespace(cp)) + break; + } + } + + _session.SelectionSize = std::max(0, _session.SelectionSize - (selectionOffset - _session.SelectionStart)); + _session.SelectionStart = selectionOffset; } void TextComposition::Insert(const utf8* text) @@ -292,17 +424,20 @@ void TextComposition::Clear() void TextComposition::Delete() { size_t selectionOffset = _session.SelectionStart; - size_t selectionMaxOffset = _session.Buffer->size(); + size_t selectionMaxOffset = std::min(_session.SelectionStart + _session.SelectionSize, _session.Buffer->size()); if (selectionOffset >= selectionMaxOffset) return; // Find out how many bytes to delete. const utf8* ch = _session.Buffer->c_str() + _session.SelectionStart; - do + while (selectionOffset < selectionMaxOffset) { - ch++; - selectionOffset++; - } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + do + { + ch++; + selectionOffset++; + } while (!UTF8IsCodepointStart(ch) && selectionOffset < selectionMaxOffset); + } size_t bytesToSkip = selectionOffset - _session.SelectionStart; if (bytesToSkip == 0) diff --git a/src/openrct2-ui/TextComposition.h b/src/openrct2-ui/TextComposition.h index 3dcc96575b..6645ed0fb3 100644 --- a/src/openrct2-ui/TextComposition.h +++ b/src/openrct2-ui/TextComposition.h @@ -37,10 +37,12 @@ namespace OpenRCT2::Ui void HandleMessage(const SDL_Event* e); private: - void CursorHome(); - void CursorEnd(); - void CursorLeft(); - void CursorRight(); + void CaretMoveToStart(); + void CaretMoveToEnd(); + void CaretMoveLeft(); + void CaretMoveRight(); + void CaretMoveToLeftToken(); + void CaretMoveToRightToken(); void Insert(const utf8* text); void InsertCodepoint(codepoint_t codepoint); void Clear(); diff --git a/src/openrct2/interface/Chat.cpp b/src/openrct2/interface/Chat.cpp index 6d3d763751..9b1ad3683b 100644 --- a/src/openrct2/interface/Chat.cpp +++ b/src/openrct2/interface/Chat.cpp @@ -163,7 +163,7 @@ void ChatDraw(DrawPixelInfo* dpi, uint8_t chatBackgroundColor) { if (i >= _chatHistory.size()) break; - + uint32_t expireTime = ChatHistoryGetTime(i) + 10000; if (!gChatOpen && Platform::GetTicks() > expireTime) {