REVIEWED: GuiTextBoxMulti() -WIP-

This commit is contained in:
Ray
2023-04-17 01:18:56 +02:00
parent e0d3c02892
commit 87fc5aa72c

View File

@ -2147,22 +2147,22 @@ bool GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + sharedCursorIndex); textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + sharedCursorIndex);
} }
int codepoint = GetCharPressed(); // Get Unicode codepoint
int textLength = (int)strlen(text); // Get current text length int textLength = (int)strlen(text); // Get current text length
int codepoint = GetCharPressed(); // Get Unicode codepoint
// Encode codepoint as UTF-8 // Encode codepoint as UTF-8
int codepointSize = 0; int codepointSize = 0;
const char *textUTF8 = CodepointToUTF8(codepoint, &codepointSize); const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
// Add codepoint to text, at current cursor position // Add codepoint to text, at current cursor position
// NOTE: Make sure we do not overflow buffer size // NOTE: Make sure we do not overflow buffer size
if ((codepoint >= 32) && ((textLength + codepointSize) < bufferSize)) if ((codepoint >= 32) && ((textLength + codepointSize) < bufferSize))
{ {
// Move forward data from cursor position // Move forward data from cursor position
for (int i = (textLength + codepointSize); i > sharedCursorIndex; i--) text[i] = text[i - 1]; for (int i = (textLength + codepointSize); i > sharedCursorIndex; i--) text[i] = text[i - codepointSize];
// Add new codepoint in current cursor position // Add new codepoint in current cursor position
for (int i = 0; i < codepointSize; i++) text[sharedCursorIndex + i] = textUTF8[i]; for (int i = 0; i < codepointSize; i++) text[sharedCursorIndex + i] = charEncoded[i];
sharedCursorIndex += codepointSize; sharedCursorIndex += codepointSize;
textLength += codepointSize; textLength += codepointSize;
@ -2211,11 +2211,8 @@ bool GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
// Finish text editing on ENTER or mouse click outside bounds // Finish text editing on ENTER or mouse click outside bounds
if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
{ {
// Exiting edit mode pressed = true; // Exiting edit mode
pressed = true; sharedCursorIndex = 0; // GLOBAL: Reset the shared cursor index
// GLOBAL: Reset the shared cursor index
sharedCursorIndex = 0;
} }
} }
else else
@ -2223,13 +2220,11 @@ bool GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
if (CheckCollisionPointRec(mousePoint, bounds)) if (CheckCollisionPointRec(mousePoint, bounds))
{ {
state = STATE_FOCUSED; state = STATE_FOCUSED;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{ {
// Entering edit mode pressed = true; // Entering edit mode
pressed = true; sharedCursorIndex = strlen(text); // GLOBAL: Place cursor index to the end of current text
// GLOBAL: Place cursor index to the end of current text
sharedCursorIndex = strlen(text);
} }
} }
} }
@ -2261,7 +2256,7 @@ bool GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
} }
// Text Box control with multiple lines // Text Box control with multiple lines
bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode)
{ {
GuiState state = guiState; GuiState state = guiState;
bool pressed = false; bool pressed = false;
@ -2284,62 +2279,88 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
{ {
state = STATE_PRESSED; state = STATE_PRESSED;
// We get an Unicode codepoint int textLength = (int)strlen(text); // Get current text length
int codepoint = GetCharPressed(); int codepoint = GetCharPressed(); // Get Unicode codepoint
int textLength = (int)strlen(text); // Length in bytes (UTF-8 string) if (IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n';
int byteSize = 0;
const char *textUTF8 = CodepointToUTF8(codepoint, &byteSize); // Encode codepoint as UTF-8
int codepointSize = 0;
const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
// Introduce characters // Introduce characters
if ((textLength + byteSize) < textSize) if (((codepoint == 10) || (codepoint >= 32)) && (textLength + codepointSize) < bufferSize)
{ {
if (IsKeyPressed(KEY_ENTER)) // Move forward data from cursor position
{ for (int i = (textLength + codepointSize); i > sharedCursorIndex; i--) text[i] = text[i - codepointSize];
text[textLength] = '\n';
textLength++; // Add new codepoint in current cursor position
} for (int i = 0; i < codepointSize; i++) text[sharedCursorIndex + i] = charEncoded[i];
else if (codepoint >= 32)
{ sharedCursorIndex += codepointSize;
// Supports Unicode inputs -> Encoded to UTF-8 textLength += codepointSize;
int charUTF8Length = 0;
const char *charEncoded = CodepointToUTF8(codepoint, &charUTF8Length); // Make sure text last character is EOL
memcpy(text + textLength, charEncoded, charUTF8Length); text[textLength] = '\0';
textLength += charUTF8Length;
}
} }
// Delete characters // Delete codepoint from text, at current cursor position
if (textLength > 0) if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE))
{ {
if (IsKeyPressed(KEY_BACKSPACE)) int prevCodepointSize = 0;
{ GetCodepointPrevious(text + sharedCursorIndex, &prevCodepointSize);
if ((unsigned char)text[textLength - 1] < 127)
{
// Remove ASCII equivalent character (1 byte)
textLength--;
text[textLength] = '\0';
}
else
{
// Remove latest UTF-8 unicode character introduced (n bytes)
int charUTF8Length = 0;
while ((charUTF8Length < textLength) && ((unsigned char)text[textLength - 1 - charUTF8Length] & 0b01000000) == 0) charUTF8Length++;
textLength -= (charUTF8Length + 1); // Move backward text from cursor position
text[textLength] = '\0'; for (int i = (sharedCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize];
}
} sharedCursorIndex -= codepointSize;
textLength -= codepointSize;
// Make sure text last character is EOL
text[textLength] = '\0';
} }
// Move cursor position with keys
/*
if (IsKeyPressed(KEY_LEFT))
{
int prevCodepointSize = 0;
GetCodepointPrevious(text + sharedCursorIndex, &prevCodepointSize);
if (sharedCursorIndex >= prevCodepointSize) sharedCursorIndex -= prevCodepointSize;
}
else if (IsKeyPressed(KEY_RIGHT))
{
int nextCodepointSize = 0;
GetCodepointNext(text + sharedCursorIndex, &nextCodepointSize);
if ((sharedCursorIndex + nextCodepointSize) <= textLength) sharedCursorIndex += nextCodepointSize;
}
*/
// TODO: Move cursor position with mouse
// TODO: Recalculate cursor position depending on sharedCursorIndex
//cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text) - GetTextWidth(text + sharedCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING);
//cursor.y = consider line breaks
// Exit edit mode // Exit edit mode
if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true; if (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
pressed = true; // Exiting edit mode
sharedCursorIndex = 0; // GLOBAL: Reset the shared cursor index
}
} }
else else
{ {
if (CheckCollisionPointRec(mousePoint, bounds)) if (CheckCollisionPointRec(mousePoint, bounds))
{ {
state = STATE_FOCUSED; state = STATE_FOCUSED;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
pressed = true; // Entering edit mode
sharedCursorIndex = strlen(text); // GLOBAL: Place cursor index to the end of current text
}
} }
} }
} }
@ -3940,9 +3961,9 @@ static Rectangle GetTextBounds(int control, Rectangle bounds)
Rectangle textBounds = bounds; Rectangle textBounds = bounds;
textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH); textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING);
textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH); textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
// Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT // Consider TEXT_PADDING properly, depends on control type and TEXT_ALIGNMENT
switch (control) switch (control)