From ec32b70e15f02d1eca3d10e08c514e41c51958c8 Mon Sep 17 00:00:00 2001 From: Casey Langen Date: Thu, 7 Jul 2016 00:49:50 -0700 Subject: [PATCH] Fixed TextInput left/right insert/delete functionality for UTF8 and multi-width characters. --- src/core/config.h | 6 +++++- src/musikbox/cursespp/TextInput.cpp | 16 ++++++++++------ src/musikbox/cursespp/TextInput.h | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/core/config.h b/src/core/config.h index 531425f48..1ae4c7167 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -87,6 +87,10 @@ inline static size_t u8len(const std::string& str) { /* get the (raw) character index of the "nth" logical/display character */ inline static size_t u8offset(const std::string& str, int n) { + if (str.size() == 0) { + return std::string::npos; + } + std::string::const_iterator it = str.begin(); int count = 0; @@ -95,7 +99,7 @@ inline static size_t u8offset(const std::string& str, int n) { ++count; } - return (size_t) count; + return (size_t) (it - str.begin()); } inline static std::string u8substr(const std::string& in, int offset, int len) { diff --git a/src/musikbox/cursespp/TextInput.cpp b/src/musikbox/cursespp/TextInput.cpp index 046122a29..fbbbf0ba1 100755 --- a/src/musikbox/cursespp/TextInput.cpp +++ b/src/musikbox/cursespp/TextInput.cpp @@ -65,7 +65,7 @@ inline static bool removeUtf8Char(std::string& value, size_t position) { } else { size_t offset = u8offset(value, position - 1); - if (offset >= 0) { + if (offset != std::string::npos) { size_t end = u8offset(value, position); value.erase(offset, end - offset); return true; @@ -94,7 +94,9 @@ size_t TextInput::Length() { } size_t TextInput::Position() { - return this->position; + /* note we return the COLUMN offset, not the physical or logical + character offset! */ + return u8cols(u8substr(this->buffer, 0, this->position)); } bool TextInput::Write(const std::string& key) { @@ -116,7 +118,9 @@ bool TextInput::Write(const std::string& key) { /* one character at a time. if it's more than one character, we're dealing with an escape sequence and should not print it. */ if (u8len(key) == 1) { - this->buffer.insert(u8offset(this->buffer, this->position), key); + size_t offset = u8offset(this->buffer, this->position); + offset = (offset == std::string::npos) ? 0 : offset; + this->buffer.insert(offset, key); this->TextChanged(this, this->buffer); ++this->position; } @@ -132,10 +136,10 @@ bool TextInput::Write(const std::string& key) { bool TextInput::KeyPress(const std::string& key) { if (key == "KEY_LEFT") { - return this->MoveCursor(-1); + return this->OffsetPosition(-1); } else if (key == "KEY_RIGHT") { - return this->MoveCursor(1); + return this->OffsetPosition(1); } else if (key == "KEY_HOME") { this->position = 0; @@ -159,7 +163,7 @@ bool TextInput::KeyPress(const std::string& key) { return false; } -bool TextInput::MoveCursor(int delta) { +bool TextInput::OffsetPosition(int delta) { int actual = this->position + delta; actual = std::max(0, std::min((int) this->bufferLength, actual)); diff --git a/src/musikbox/cursespp/TextInput.h b/src/musikbox/cursespp/TextInput.h index e34050920..3e8142d4c 100755 --- a/src/musikbox/cursespp/TextInput.h +++ b/src/musikbox/cursespp/TextInput.h @@ -67,7 +67,7 @@ namespace cursespp { virtual std::string GetText() { return this->buffer; } private: - bool MoveCursor(int delta); + bool OffsetPosition(int delta); std::string buffer; int position;