diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-11-05 23:59:18 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-11-05 23:59:18 +0100 |
commit | f7246d83d2f43e0088e2a01ff6305ac7e25f21fe (patch) | |
tree | 293bb9545f85374885c478a04089c6c983b6194a /src | |
parent | 5836c731bd57a6d892f77d7d0c52e6bf74bde0a1 (diff) |
Fix possible crash on backspace in edit text with invalid utf8
Diffstat (limited to 'src')
-rw-r--r-- | src/Text.cpp | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/src/Text.cpp b/src/Text.cpp index 192061f..0b6347d 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -510,21 +510,11 @@ namespace QuickMedia if(emoji_codepoint_combined == "1f441-fe0f-200d-1f5e8-fe0f") emoji_codepoint_combined = "1f441-200d-1f5e8"; - std::string image_url; - bool image_local = false; - if(emoji_codepoint_combined != "1f3f3-fe0f-200d-26a7-fe0f") { - image_url = "/usr/share/quickmedia/emoji/" + emoji_codepoint_combined + ".png"; - image_local = true; - } else { - image_url = "/usr/share/quickmedia/images/troonjak.png"; - image_local = true; - } - text_element.create_text("E"); text_element.text_type = TextElement::TextType::EMOJI; text_element.text = "E"; - text_element.url = std::move(image_url); - text_element.local = image_local; + text_element.url = "/usr/share/quickmedia/emoji/" + emoji_codepoint_combined + ".png"; + text_element.local = true; text_element.size = { (int)vspace, (int)vspace }; text_element.text_num_bytes = emoji_byte_length; text_elements.push_back(std::move(text_element)); @@ -602,6 +592,23 @@ namespace QuickMedia static mgl::vec2f vec2f_floor(mgl::vec2f value) { return mgl::vec2f((int)value.x, (int)value.y); } + + static size_t utf8_get_num_codepoints(const char *str, size_t size) { + size_t codepoint_index = 0; + for(size_t i = 0; i < size;) { + unsigned char *cp = (unsigned char*)&str[i]; + uint32_t codepoint; + size_t clen; + if(!mgl::utf8_decode(cp, size - i, &codepoint, &clen)) { + codepoint = *cp; + clen = 1; + } + + i += clen; + ++codepoint_index; + } + return codepoint_index; + } void Text::updateGeometry(bool update_even_if_not_dirty) { if(dirtyText) { @@ -1183,6 +1190,9 @@ namespace QuickMedia } else if(event.key.code == mgl::Keyboard::Backspace && caretIndex > 0) { + if(caretIndex < 0 || caretIndex > (int)vertices_linear.size()) + return; + const size_t str_index = get_string_index_from_caret_index(caretIndex); if(str_index > 0 && str_index <= str.size()) { const size_t codepoint_start = str_index - vertices_linear[caretIndex - 1].text_num_bytes; @@ -1195,6 +1205,9 @@ namespace QuickMedia } else if(event.key.code == mgl::Keyboard::Delete && !caretAtEnd) { + if(caretIndex < 0 || caretIndex >= (int)vertices_linear.size()) + return; + const size_t str_index = get_string_index_from_caret_index(caretIndex); const size_t codepoint_end = str_index + vertices_linear[caretIndex].text_num_bytes; if(str_index < str.size() && codepoint_end <= str.size()) { @@ -1266,10 +1279,11 @@ namespace QuickMedia std::vector<TextElement> new_text_elements; split_text_by_type(new_text_elements, stringToAdd); for(auto &text_element : new_text_elements) { - if(text_element.type == TextElement::Type::IMAGE || text_element.text_type == TextElement::TextType::EMOJI) + if(text_element.type == TextElement::Type::IMAGE || text_element.text_type == TextElement::TextType::EMOJI) { caretIndex += 1; - else - caretIndex += text_element.text_num_bytes; + } else { + caretIndex += utf8_get_num_codepoints(text_element.text.data(), text_element.text.size()); + } } dirty = true; dirtyText = true; |