mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge pull request #3121 from OpenRCT2/fix-3091
fix #3091: Korean words corrupted if over byte limit
This commit is contained in:
commit
53cd4c7935
|
@ -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 = "<group>"; };
|
||||
001085EF1C90FD030075A2AD /* textinputbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textinputbuffer.h; sourceTree = "<group>"; };
|
||||
C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawing_fast.cpp; sourceTree = "<group>"; };
|
||||
D4163F671C2A044D00B83136 /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = "<group>"; };
|
||||
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 */,
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<ClCompile Include="src\core\Path.cpp" />
|
||||
<ClCompile Include="src\core\Stopwatch.cpp" />
|
||||
<ClCompile Include="src\core\String.cpp" />
|
||||
<ClCompile Include="src\core\textinputbuffer.c" />
|
||||
<ClCompile Include="src\cursors.c" />
|
||||
<ClCompile Include="src\diagnostic.c" />
|
||||
<ClCompile Include="src\drawing\drawing.c" />
|
||||
|
@ -217,6 +218,7 @@
|
|||
<ClInclude Include="src\core\String.hpp" />
|
||||
<ClInclude Include="src\core\StringBuilder.hpp" />
|
||||
<ClInclude Include="src\core\StringReader.hpp" />
|
||||
<ClInclude Include="src\core\textinputbuffer.h" />
|
||||
<ClInclude Include="src\core\Util.hpp" />
|
||||
<ClInclude Include="src\cursors.h" />
|
||||
<ClInclude Include="src\diagnostic.h" />
|
||||
|
|
|
@ -584,6 +584,9 @@
|
|||
<ClCompile Include="src\drawing\drawing_fast.cpp">
|
||||
<Filter>Source\Drawing</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\core\textinputbuffer.c">
|
||||
<Filter>Source\Core</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\management\award.h">
|
||||
|
@ -890,5 +893,8 @@
|
|||
<ClInclude Include="src\core\Guard.hpp" />
|
||||
<ClInclude Include="src\core\Diagnostics.hpp" />
|
||||
<ClInclude Include="src\core\Json.hpp" />
|
||||
<ClInclude Include="src\core\textinputbuffer.h">
|
||||
<Filter>Source\Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <SDL.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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 <CTRL>Backspace (Windows/Linux) or <MOD>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;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "util.h"
|
||||
// Include common.h before SDL, otherwise M_PI gets redefined
|
||||
#include "../common.h"
|
||||
|
||||
#include <SDL.h>
|
||||
#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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue