#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers /***************************************************************************** * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. * * OpenRCT2 is the work of many authors, a full list can be found in contributors.md * For more information, visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * A full copy of the GNU General Public License can be found in licence.txt *****************************************************************************/ #pragma endregion #include "../localisation/localisation.h" #include "textinputbuffer.h" void textinputbuffer_init(textinputbuffer * tib, utf8 * buffer, size_t size) { assert(buffer != NULL); assert(size > 0); tib->buffer = buffer; tib->max_size = size - 1; tib->current_size = strlen(buffer); tib->selection_offset = tib->current_size; tib->selection_size = 0; textinputbuffer_recalculate_length(tib); } void textinputbuffer_clear(textinputbuffer * tib) { tib->buffer[0] = 0; tib->current_size = 0; tib->length = 0; tib->selection_offset = 0; tib->selection_size = 0; } void textinputbuffer_remove_selected(textinputbuffer * tib) { utf8 * targetShiftPtr = tib->buffer + tib->selection_offset; utf8 * sourceShiftPtr = targetShiftPtr + tib->selection_size; size_t shiftSize = tib->current_size - tib->selection_offset - tib->selection_size + 1; memmove(targetShiftPtr, sourceShiftPtr, shiftSize); tib->selection_size = 0; textinputbuffer_recalculate_length(tib); } void textinputbuffer_insert_codepoint(textinputbuffer * tib, uint32 codepoint) { size_t codepointLength = utf8_get_codepoint_length(codepoint); size_t remainingSize = tib->max_size - tib->current_size; if (codepointLength <= remainingSize) { utf8 * insertPtr = tib->buffer + tib->selection_offset; if (tib->selection_offset < tib->current_size) { // Shift bytes (including null terminator) right to make room for new codepoint utf8 * targetShiftPtr = insertPtr + codepointLength; size_t shiftSize = tib->current_size - tib->selection_offset + 1; memmove(targetShiftPtr, insertPtr, shiftSize); } else { // Character is appended onto the end, so set byte after it to null terminator tib->buffer[tib->current_size + codepointLength] = 0; } utf8_write_codepoint(insertPtr, codepoint); tib->selection_offset += codepointLength; tib->current_size += codepointLength; tib->length++; } } void textinputbuffer_insert(textinputbuffer * tib, utf8 * source) { const utf8 *ch = source; uint32 codepoint; while ((codepoint = utf8_get_next(ch, &ch)) != 0) { textinputbuffer_insert_codepoint(tib, codepoint); } } void textinputbuffer_cursor_left(textinputbuffer * tib) { size_t selectionOffset = tib->selection_offset; if (selectionOffset > 0) { const utf8 * ch = tib->buffer + selectionOffset; do { ch--; selectionOffset--; } while (!utf8_is_codepoint_start(ch) && selectionOffset > 0); tib->selection_offset = selectionOffset; } } void textinputbuffer_cursor_right(textinputbuffer * tib) { size_t selectionOffset = tib->selection_offset; size_t selectionMaxOffset = tib->current_size; if (selectionOffset < selectionMaxOffset) { const utf8 * ch = tib->buffer + selectionOffset; do { ch++; selectionOffset++; } while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset); tib->selection_size = max(0, tib->selection_size - (selectionOffset - tib->selection_offset)); tib->selection_offset = selectionOffset; } } void textinputbuffer_cursor_home(textinputbuffer * tib) { tib->selection_offset = 0; } void textinputbuffer_cursor_end(textinputbuffer * tib) { tib->selection_offset = tib->current_size; } void textinputbuffer_recalculate_length(textinputbuffer * tib) { tib->current_size = strlen(tib->buffer); tib->length = utf8_length(tib->buffer); }