summaryrefslogtreecommitdiff
path: root/src/ui_elements/TextEditor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui_elements/TextEditor.c')
-rw-r--r--src/ui_elements/TextEditor.c118
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);
+}