From 1daa6576575f9a1fbef321236c0368396b5ff3df Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 9 Mar 2016 23:07:55 +0000 Subject: [PATCH 1/2] fix #3091: Korean words corrupted if over byte limit --- openrct2.vcxproj | 2 + openrct2.vcxproj.filters | 6 ++ src/core/textinputbuffer.c | 114 +++++++++++++++++++++++++++++ src/core/textinputbuffer.h | 28 +++++++ src/interface/chat.c | 4 +- src/interface/console.c | 17 +++-- src/interface/widget.c | 6 +- src/localisation/language.h | 2 +- src/localisation/user.c | 2 +- src/localisation/utf8.c | 2 +- src/platform/platform.h | 4 +- src/platform/shared.c | 141 ++++++++++++------------------------ src/util/util.c | 60 ++++++++++----- src/util/util.h | 1 + src/windows/text_input.c | 8 +- 15 files changed, 263 insertions(+), 134 deletions(-) create mode 100644 src/core/textinputbuffer.c create mode 100644 src/core/textinputbuffer.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 3ab8b8c9aa..3b5ae319ce 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -34,6 +34,7 @@ + @@ -217,6 +218,7 @@ + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index d9a36792a2..333e9eccff 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -584,6 +584,9 @@ Source\Drawing + + Source\Core + @@ -890,5 +893,8 @@ + + Source\Core + \ No newline at end of file diff --git a/src/core/textinputbuffer.c b/src/core/textinputbuffer.c new file mode 100644 index 0000000000..5ddaaf051f --- /dev/null +++ b/src/core/textinputbuffer.c @@ -0,0 +1,114 @@ +#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); +} diff --git a/src/core/textinputbuffer.h b/src/core/textinputbuffer.h new file mode 100644 index 0000000000..582e8f8933 --- /dev/null +++ b/src/core/textinputbuffer.h @@ -0,0 +1,28 @@ +#ifndef _TEXTINPUTBUFFER_H_ +#define _TEXTINPUTBUFFER_H_ + +#include "../common.h" + +typedef struct { + utf8 * buffer; + size_t max_size; // Maximum number of bytes (excluding null terminator) + size_t current_size; // Number of bytes (excluding null terminator) + + uint32 length; // Number of codepoints + + size_t selection_offset; // Selection start, in bytes + size_t selection_size; // Selection length in bytes +} textinputbuffer; + +void textinputbuffer_init(textinputbuffer * tib, utf8 * buffer, size_t size); +void textinputbuffer_clear(textinputbuffer * tib); +void textinputbuffer_remove_selected(textinputbuffer * tib); +void textinputbuffer_insert_codepoint(textinputbuffer * tib, uint32 codepoint); +void textinputbuffer_insert(textinputbuffer * tib, utf8 * source); +void textinputbuffer_cursor_left(textinputbuffer * tib); +void textinputbuffer_cursor_right(textinputbuffer * tib); +void textinputbuffer_cursor_home(textinputbuffer * tib); +void textinputbuffer_cursor_end(textinputbuffer * tib); +void textinputbuffer_recalculate_length(textinputbuffer * tib); + +#endif diff --git a/src/interface/chat.c b/src/interface/chat.c index 7bfecbfec5..0166239cf9 100644 --- a/src/interface/chat.c +++ b/src/interface/chat.c @@ -91,8 +91,8 @@ void chat_draw() gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer) + 7, y + 12); gfx_draw_string(dpi, lineBuffer, 255, x, y); if (_chatCaretTicks < 15) { - memcpy(lineBuffer, _chatCurrentLine, gTextInputCursorPosition); - lineBuffer[gTextInputCursorPosition] = 0; + memcpy(lineBuffer, _chatCurrentLine, gTextInput.selection_offset); + lineBuffer[gTextInput.selection_offset] = 0; int caretX = x + gfx_get_string_width(lineBuffer); int caretY = y + 15; diff --git a/src/interface/console.c b/src/interface/console.c index 7d4e2d0e0e..5ebea50aaf 100644 --- a/src/interface/console.c +++ b/src/interface/console.c @@ -214,8 +214,8 @@ void console_draw(rct_drawpixelinfo *dpi) // Draw caret if (_consoleCaretTicks < 15) { - memcpy(lineBuffer, _consoleCurrentLine, gTextInputCursorPosition); - lineBuffer[gTextInputCursorPosition] = 0; + memcpy(lineBuffer, _consoleCurrentLine, gTextInput.selection_offset); + lineBuffer[gTextInput.selection_offset] = 0; int caretX = x + gfx_get_string_width(lineBuffer); int caretY = y + lineHeight; @@ -249,15 +249,15 @@ void console_input(int c) _consoleHistoryIndex--; memcpy(_consoleCurrentLine, _consoleHistory[_consoleHistoryIndex], 256); } - gTextInputCursorPosition = strlen(_consoleCurrentLine); - gTextInputLength = gTextInputCursorPosition; + textinputbuffer_recalculate_length(&gTextInput); + gTextInput.selection_offset = strlen(_consoleCurrentLine); break; case SDL_SCANCODE_DOWN: if (_consoleHistoryIndex < _consoleHistoryCount - 1) { _consoleHistoryIndex++; memcpy(_consoleCurrentLine, _consoleHistory[_consoleHistoryIndex], 256); - gTextInputCursorPosition = strlen(_consoleCurrentLine); - gTextInputLength = gTextInputCursorPosition; + textinputbuffer_recalculate_length(&gTextInput); + gTextInput.selection_offset = strlen(_consoleCurrentLine); } else { _consoleHistoryIndex = _consoleHistoryCount; console_clear_input(); @@ -389,8 +389,9 @@ void console_refresh_caret() static void console_clear_input() { _consoleCurrentLine[0] = 0; - gTextInputCursorPosition = 0; - gTextInputLength = 0; + gTextInput.selection_offset = 0; + gTextInput.selection_size = 0; + textinputbuffer_recalculate_length(&gTextInput); } static void console_history_add(const utf8 *src) diff --git a/src/interface/widget.c b/src/interface/widget.c index f161dea94c..23ccbb16a0 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -1191,15 +1191,15 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg // Make a copy of the string for measuring the width. char temp_string[512] = { 0 }; - memcpy(temp_string, wrapped_string, min(string_length, gTextInputCursorPosition)); + memcpy(temp_string, wrapped_string, min((size_t)string_length, gTextInput.selection_offset)); int cur_x = l + gfx_get_string_width(temp_string) + 3; int width = 6; - if ((uint32)gTextInputCursorPosition < strlen(gTextBoxInput)){ + if ((uint32)gTextInput.selection_offset < strlen(gTextBoxInput)){ // Make a new 1 character wide string for measuring the width // of the character that the cursor is under. temp_string[1] = '\0'; - temp_string[0] = gTextBoxInput[gTextInputCursorPosition]; + temp_string[0] = gTextBoxInput[gTextInput.selection_offset]; width = max(gfx_get_string_width(temp_string) - 2, 4); } diff --git a/src/localisation/language.h b/src/localisation/language.h index 2bc21de39b..5f12220d8f 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -78,7 +78,7 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/ uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr); utf8 *utf8_write_codepoint(utf8 *dst, uint32 codepoint); int utf8_insert_codepoint(utf8 *dst, uint32 codepoint); -bool utf8_is_codepoint_start(utf8 *text); +bool utf8_is_codepoint_start(const utf8 *text); void utf8_remove_format_codes(utf8 *text, bool allowcolours); int utf8_get_codepoint_length(int codepoint); int utf8_length(const utf8 *text); diff --git a/src/localisation/user.c b/src/localisation/user.c index 951586b792..7e56d214a0 100644 --- a/src/localisation/user.c +++ b/src/localisation/user.c @@ -55,7 +55,7 @@ rct_string_id user_string_allocate(int base, const utf8 *text) if (userString[0] != 0) continue; - safe_strcpy(userString, text, USER_STRING_MAX_LENGTH - 1); + safe_strcpy(userString, text, USER_STRING_MAX_LENGTH); return 0x8000 + (i | highBits); } RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_NAMES_DEFINED; diff --git a/src/localisation/utf8.c b/src/localisation/utf8.c index e6403e1399..34963cb2d2 100644 --- a/src/localisation/utf8.c +++ b/src/localisation/utf8.c @@ -65,7 +65,7 @@ int utf8_insert_codepoint(utf8 *dst, uint32 codepoint) return shift; } -bool utf8_is_codepoint_start(utf8 *text) +bool utf8_is_codepoint_start(const utf8 *text) { if ((text[0] & 0x80) == 0) return true; if ((text[0] & 0xC0) == 0xC0) return true; diff --git a/src/platform/platform.h b/src/platform/platform.h index b0db9eddb2..1e158f8109 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -29,6 +29,7 @@ #include +#include "../core/textinputbuffer.h" #include "../drawing/font.h" #ifndef MAX_PATH @@ -92,9 +93,8 @@ extern openrct2_cursor gCursorState; extern const unsigned char *gKeysState; extern unsigned char *gKeysPressed; extern unsigned int gLastKeyPressed; -extern int gTextInputCursorPosition; -extern int gTextInputLength; +extern textinputbuffer gTextInput; extern bool gTextInputCompositionActive; extern utf8 gTextInputComposition[32]; extern int gTextInputCompositionStart; diff --git a/src/platform/shared.c b/src/platform/shared.c index b690730e28..1a8bfc935f 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -42,10 +42,7 @@ openrct2_cursor gCursorState; const unsigned char *gKeysState; unsigned char *gKeysPressed; unsigned int gLastKeyPressed; -utf8 *gTextInput; -int gTextInputLength; -int gTextInputMaxLength; -int gTextInputCursorPosition = 0; +textinputbuffer gTextInput; bool gTextInputCompositionActive; utf8 gTextInputComposition[32]; @@ -594,90 +591,59 @@ void platform_process_messages() } // Text input + if (gTextInput.buffer == NULL) break; // Clear the input on Backspace (Windows/Linux) or Backspace (OS X) - if (gTextInput != NULL && e.key.keysym.sym == SDLK_BACKSPACE && (e.key.keysym.mod & KEYBOARD_PRIMARY_MODIFIER)) { - memset(gTextInput, '\0', gTextInputMaxLength); - gTextInputCursorPosition = 0; - gTextInputLength = 0; + if (e.key.keysym.sym == SDLK_BACKSPACE && (e.key.keysym.mod & KEYBOARD_PRIMARY_MODIFIER)) { + textinputbuffer_clear(&gTextInput); console_refresh_caret(); window_update_textbox(); } // If backspace and we have input text with a cursor position none zero - if (e.key.keysym.sym == SDLK_BACKSPACE && gTextInputLength > 0 && gTextInput != NULL && gTextInputCursorPosition) { - int dstIndex = gTextInputCursorPosition; - do { - if (dstIndex == 0) break; - dstIndex--; - } while (!utf8_is_codepoint_start(&gTextInput[dstIndex])); - int removedCodepointSize = gTextInputCursorPosition - dstIndex; + if (e.key.keysym.sym == SDLK_BACKSPACE) { + if (gTextInput.selection_offset > 0) { + size_t endOffset = gTextInput.selection_offset; + textinputbuffer_cursor_left(&gTextInput); + gTextInput.selection_size = endOffset - gTextInput.selection_offset; + textinputbuffer_remove_selected(&gTextInput); - // When at max length don't shift the data left - // as it would buffer overflow. - if (gTextInputCursorPosition != gTextInputMaxLength) { - memmove(gTextInput + dstIndex, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - dstIndex); + console_refresh_caret(); + window_update_textbox(); } - gTextInput[gTextInputLength - removedCodepointSize] = '\0'; - gTextInputCursorPosition -= removedCodepointSize; - gTextInputLength -= removedCodepointSize; - console_refresh_caret(); - window_update_textbox(); - } - if (e.key.keysym.sym == SDLK_END){ - gTextInputCursorPosition = gTextInputLength; - console_refresh_caret(); } if (e.key.keysym.sym == SDLK_HOME) { - gTextInputCursorPosition = 0; + textinputbuffer_cursor_home(&gTextInput); console_refresh_caret(); } - if (e.key.keysym.sym == SDLK_DELETE && gTextInputLength > 0 && gTextInput != NULL && gTextInputCursorPosition != gTextInputLength) { - int dstIndex = gTextInputCursorPosition; - do { - if (dstIndex == gTextInputLength) break; - dstIndex++; - } while (!utf8_is_codepoint_start(&gTextInput[dstIndex])); - int removedCodepointSize = dstIndex - gTextInputCursorPosition; - - memmove(gTextInput + gTextInputCursorPosition, gTextInput + dstIndex, gTextInputMaxLength - dstIndex); - gTextInput[gTextInputMaxLength - removedCodepointSize] = '\0'; - gTextInputLength -= removedCodepointSize; + if (e.key.keysym.sym == SDLK_END) { + textinputbuffer_cursor_end(&gTextInput); + console_refresh_caret(); + } + if (e.key.keysym.sym == SDLK_DELETE) { + size_t startOffset = gTextInput.selection_offset; + textinputbuffer_cursor_right(&gTextInput); + gTextInput.selection_size = gTextInput.selection_offset - startOffset; + gTextInput.selection_offset = startOffset; + textinputbuffer_remove_selected(&gTextInput); console_refresh_caret(); window_update_textbox(); } - if (e.key.keysym.sym == SDLK_RETURN && gTextInput != NULL) { + if (e.key.keysym.sym == SDLK_RETURN) { window_cancel_textbox(); } - if (e.key.keysym.sym == SDLK_LEFT && gTextInput != NULL) { - do { - if (gTextInputCursorPosition == 0) break; - gTextInputCursorPosition--; - } while (!utf8_is_codepoint_start(&gTextInput[gTextInputCursorPosition])); + if (e.key.keysym.sym == SDLK_LEFT) { + textinputbuffer_cursor_left(&gTextInput); console_refresh_caret(); } - else if (e.key.keysym.sym == SDLK_RIGHT && gTextInput != NULL) { - do { - if (gTextInputCursorPosition == gTextInputLength) break; - gTextInputCursorPosition++; - } while (!utf8_is_codepoint_start(&gTextInput[gTextInputCursorPosition])); + else if (e.key.keysym.sym == SDLK_RIGHT) { + textinputbuffer_cursor_right(&gTextInput); console_refresh_caret(); } - else if (e.key.keysym.sym == SDLK_v && (SDL_GetModState() & KEYBOARD_PRIMARY_MODIFIER) && gTextInput != NULL) { + else if (e.key.keysym.sym == SDLK_v && (SDL_GetModState() & KEYBOARD_PRIMARY_MODIFIER)) { if (SDL_HasClipboardText()) { utf8 *text = SDL_GetClipboardText(); - for (int i = 0; text[i] != '\0' && gTextInputLength < gTextInputMaxLength; i++) { - // If inserting in center of string make space for new letter - if (gTextInputLength > gTextInputCursorPosition){ - memmove(gTextInput + gTextInputCursorPosition + 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1); - gTextInput[gTextInputCursorPosition] = text[i]; - gTextInputLength++; - } else { - gTextInput[gTextInputLength++] = text[i]; - } - gTextInputCursorPosition++; - } - gTextInput[gTextInputLength] = '\0'; + textinputbuffer_insert(&gTextInput, text); window_update_textbox(); } } @@ -713,33 +679,22 @@ void platform_process_messages() // so, set gTextInputCompositionActive to false. gTextInputCompositionActive = false; - if (gTextInputLength < gTextInputMaxLength && gTextInput){ - // HACK ` will close console, so don't input any text - if (e.text.text[0] == '`' && gConsoleOpen) - break; + if (gTextInput.buffer == NULL) break; - // Entering formatting characters is not allowed - if (utf8_is_format_code(utf8_get_next(e.text.text, NULL))) - break; - - utf8 *newText = e.text.text; - int newTextLength = strlen(newText); - - // If inserting in center of string make space for new letter - if (gTextInputLength > gTextInputCursorPosition) { - memmove(gTextInput + gTextInputCursorPosition + newTextLength, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - newTextLength); - memcpy(&gTextInput[gTextInputCursorPosition], newText, newTextLength); - gTextInputLength += newTextLength; - } else { - memcpy(&gTextInput[gTextInputLength], newText, newTextLength); - gTextInputLength += newTextLength; - gTextInput[gTextInputLength] = 0; - } - - gTextInputCursorPosition += newTextLength; - console_refresh_caret(); - window_update_textbox(); + // HACK ` will close console, so don't input any text + if (e.text.text[0] == '`' && gConsoleOpen) { + break; } + + // Entering formatting characters is not allowed + if (utf8_is_format_code(utf8_get_next(e.text.text, NULL))) { + break; + } + + utf8 *newText = e.text.text; + textinputbuffer_insert(&gTextInput, newText); + console_refresh_caret(); + window_update_textbox(); break; default: break; @@ -863,16 +818,14 @@ void platform_start_text_input(char* buffer, int max_length) SDL_SetTextInputRect(&rect); SDL_StartTextInput(); - gTextInputMaxLength = max_length - 1; - gTextInput = buffer; - gTextInputCursorPosition = strnlen(gTextInput, max_length); - gTextInputLength = gTextInputCursorPosition; + + textinputbuffer_init(&gTextInput, buffer, max_length); } void platform_stop_text_input() { SDL_StopTextInput(); - gTextInput = NULL; + gTextInput.buffer = NULL; gTextInputCompositionActive = false; } diff --git a/src/util/util.c b/src/util/util.c index 595c430467..0fd354e173 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -18,9 +18,13 @@ * along with this program. If not, see . *****************************************************************************/ -#include "util.h" +// Include common.h before SDL, otherwise M_PI gets redefined +#include "../common.h" + #include +#include "../localisation/localisation.h" #include "../platform/platform.h" +#include "util.h" #include "zlib.h" bool gUseRLE = true; @@ -202,31 +206,51 @@ int strcicmp(char const *a, char const *b) } } +utf8 * safe_strtrunc(utf8 * text, size_t size) +{ + assert(text != NULL); + + if (size == 0) return text; + + const char *sourceLimit = text + size - 1; + char *ch = text; + char *last = text; + uint32 codepoint; + while ((codepoint = utf8_get_next(ch, &ch)) != 0) { + if (ch <= sourceLimit) { + last = ch; + } else { + break; + } + } + *last = 0; + + return text; +} + char *safe_strcpy(char * destination, const char * source, size_t size) { assert(destination != NULL); assert(source != NULL); - if (size == 0) - { - return destination; - } - char *result = destination; - bool terminated = false; - for (size_t i = 0; i < size; i++) - { - if (*source != '\0') - { - *destination++ = *source++; + if (size == 0) return destination; + + char * result = destination; + + bool truncated = false; + const char *sourceLimit = source + size - 1; + const char *ch = source; + uint32 codepoint; + while ((codepoint = utf8_get_next(ch, &ch)) != 0) { + if (ch <= sourceLimit) { + destination = utf8_write_codepoint(destination, codepoint); } else { - *destination = *source; - terminated = true; - break; + truncated = true; } } - if (!terminated) - { - result[size - 1] = '\0'; + *destination = 0; + + if (truncated) { log_warning("Truncating string \"%s\" to %d bytes.", result, size); } return result; diff --git a/src/util/util.h b/src/util/util.h index f89bf95fed..e20d536745 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -43,6 +43,7 @@ int bitscanforward(int source); int bitcount(int source); bool strequals(const char *a, const char *b, int length, bool caseInsensitive); int strcicmp(char const *a, char const *b); +utf8 * safe_strtrunc(utf8 * text, size_t size); char *safe_strcpy(char * destination, const char * source, size_t num); char *safe_strcat(char *destination, const char *source, size_t size); char *safe_strcat_path(char *destination, const char *source, size_t size); diff --git a/src/windows/text_input.c b/src/windows/text_input.c index 7cf1027832..d9404443ae 100644 --- a/src/windows/text_input.c +++ b/src/windows/text_input.c @@ -293,19 +293,19 @@ static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi) int string_length = get_string_size(wrap_pointer) - 1; - if (!cur_drawn && (gTextInputCursorPosition <= char_count + string_length)) { + if (!cur_drawn && (gTextInput.selection_offset <= (size_t)(char_count + string_length))) { // Make a copy of the string for measuring the width. char temp_string[512] = { 0 }; - memcpy(temp_string, wrap_pointer, gTextInputCursorPosition - char_count); + memcpy(temp_string, wrap_pointer, gTextInput.selection_offset - char_count); cursorX = w->x + 13 + gfx_get_string_width(temp_string); cursorY = y; int width = 6; - if ((uint32)gTextInputCursorPosition < strlen(text_input)){ + if ((uint32)gTextInput.selection_offset < strlen(text_input)){ // Make a new 1 character wide string for measuring the width // of the character that the cursor is under. temp_string[1] = '\0'; - temp_string[0] = text_input[gTextInputCursorPosition]; + temp_string[0] = text_input[gTextInput.selection_offset]; width = max(gfx_get_string_width(temp_string) - 2, 4); } From b694246fb5c5e83de81c59c202d268156f78e441 Mon Sep 17 00:00:00 2001 From: YJSoft Date: Thu, 10 Mar 2016 09:54:38 +0900 Subject: [PATCH 2/2] #3121 add textinputbuffer source to xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 1a85788b3e..72ec93e595 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 001085F01C90FD030075A2AD /* textinputbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 001085EE1C90FD030075A2AD /* textinputbuffer.c */; }; C62A08D51C787C2A00F3AA76 /* drawing_fast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */; }; D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; D41B73F11C21018C0080A7B9 /* libssl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73F01C21018C0080A7B9 /* libssl.tbd */; }; @@ -221,6 +222,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 001085EE1C90FD030075A2AD /* textinputbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = textinputbuffer.c; sourceTree = ""; }; + 001085EF1C90FD030075A2AD /* textinputbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textinputbuffer.h; sourceTree = ""; }; C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawing_fast.cpp; sourceTree = ""; }; D4163F671C2A044D00B83136 /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = ""; }; D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; @@ -734,6 +737,8 @@ D4EC46E51C26342F0024B507 /* core */ = { isa = PBXGroup; children = ( + 001085EE1C90FD030075A2AD /* textinputbuffer.c */, + 001085EF1C90FD030075A2AD /* textinputbuffer.h */, D4B63B931C43028200367A37 /* Console.cpp */, D4B63B941C43028200367A37 /* Console.hpp */, D4A3511A1C6067B000CBCBA4 /* Diagnostics.hpp */, @@ -1383,6 +1388,7 @@ D4EC481A1C26342F0024B507 /* posix.c in Sources */, D4D35E2C1C45BD9B00AAFCB4 /* Path.cpp in Sources */, D4B63B981C43028F00367A37 /* String.cpp in Sources */, + 001085F01C90FD030075A2AD /* textinputbuffer.c in Sources */, D4A351211C60680300CBCBA4 /* Theme.cpp in Sources */, D4EC47E31C26342F0024B507 /* cmdline_sprite.c in Sources */, D4EC48611C26342F0024B507 /* text_input.c in Sources */,