diff options
Diffstat (limited to 'src/ui_elements/TextEditor.c')
| -rw-r--r-- | src/ui_elements/TextEditor.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c new file mode 100644 index 0000000..ca2d270 --- /dev/null +++ b/src/ui_elements/TextEditor.c @@ -0,0 +1,118 @@ +#include "UI.h" +#include "../resources/resources.h" +#include <raylib.h> +#include <stdlib.h> +#include <string.h> + +void HighlightCharacter(Vector2 lineStartPos, char *line, int index, Font *font, int height, int spacing) { + float x_position = 0; + for (int i = 0; i < index; i++) { + x_position += MeasureChar(font, height, line[i]); + x_position += spacing; + } + DrawLine(lineStartPos.x + x_position, lineStartPos.y, + lineStartPos.x + x_position, lineStartPos.y + height, COLORSCHEME_ORANGE); +} + +TextNode *CreateNode(TextNode *prev, TextNode *next) { + TextNode *node = malloc(sizeof(TextNode)); + if (node == NULL) return NULL; + node->NextNode = next; + node->PrevNode = prev; + node->text = malloc(DEFAULT_TEXT_NODE_SIZE); + if (node->text != NULL) node->cap = DEFAULT_TEXT_NODE_SIZE; + return node; +} + +/// Recursively frees the nodes +void FreeNodeRec(TextNode *node) { + if (node == NULL) return; + FreeNodeRec(node->NextNode); + free(node->text); + free(node); +} + +TextArea *CreateTextArea() { + TextArea *outp = malloc(sizeof(TextArea)); + if (outp == NULL) return NULL; + + TextNode *start_node = CreateNode(NULL, NULL); + if (start_node == NULL) { + free(outp); + return NULL; + } + + outp->StartNode = start_node; + outp->CurrentNode = start_node; + outp->NodeLenth = 1; + return outp; +} + +void FreeTextArea(TextArea *ta) { + FreeNodeRec(ta->StartNode); + free(ta); +} + +/// draws a text area on the screen. Main draw entry point +void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing) { + Vector2 pos = { .x = rec.x, .y = rec.y }; + TextNode *node = ta->StartNode; + while (node != NULL) { + DrawTextEx(*font, node->text, pos, height, spacing, COLORSCHEME_BROWN); + if (node == ta->CurrentNode) + HighlightCharacter(pos, node->text, ta->CursorPosition.x, font, height, spacing); + node = node->NextNode; + pos.x += height; + } +} + +void MoveCursorRight(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + ta->CursorPosition.x += 1; +} + +void MoveCursorLeft(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + ta->CursorPosition.x -= 1; + if (ta->CursorPosition.x < 0) ta->CursorPosition.x = 0; +} + +void InsertChar(TextArea *ta, char new_char) { + if (ta == NULL || ta->CurrentNode == NULL) return; + (ta->CurrentNode->text)[(int)ta->CursorPosition.x] = new_char; + ta->CursorPosition.x += 1; + size_t line_len = strlen(ta->CurrentNode->text); + if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len; +} + +void DeleteChar(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + if (ta->CursorPosition.x == 0) return; + size_t line_len = strlen(ta->CurrentNode->text); + + if (ta->CursorPosition.x == line_len) { + ta->CurrentNode->text[line_len - 1] = 0x0; + } else { + char *after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x); + strcpy(ta->CurrentNode->text + (int)ta->CursorPosition.x - 1, after_str); + } + ta->CursorPosition.x -= 1; +} + +bool IsKeyPressedFix(int key) { + return IsKeyPressedRepeat(key) || IsKeyPressed(key); +} + +void HandleKeyboard(TextArea *ta) { + int charKey = GetCharPressed(); + while (charKey > 0) { + if (charKey >= 32 && charKey <= 125) { + InsertChar(ta, (char)charKey); + } + charKey = GetCharPressed(); + } + + if (IsKeyPressedFix(KEY_BACKSPACE)) DeleteChar(ta); + if (IsKeyPressedFix(KEY_LEFT)) MoveCursorLeft(ta); + if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRight(ta); +} |
