summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-07-09 01:18:49 +0500
committerPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-07-09 01:18:49 +0500
commit7f7822f1bb74d3a86da5f021b35559d4509f7e08 (patch)
tree51f76f3d22da874391f37230f576f89ca9be1969 /src
parentd9b6fb98ab3f53598d79a183195964b0306c91c7 (diff)
vertical movement + raygui deletion
Diffstat (limited to 'src')
-rw-r--r--src/main.c4
-rw-r--r--src/ui_elements/TextEditor.c198
-rw-r--r--src/ui_elements/UI.h4
3 files changed, 197 insertions, 9 deletions
diff --git a/src/main.c b/src/main.c
index 1131db9..8aa83e5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,3 +1,4 @@
+
#include <stdio.h>
#include <raylib.h>
#include "scenes/scenes.h"
@@ -23,12 +24,15 @@ int main(void) {
InitWindow(800, 600, "Programming game");
LoadResources();
+ SetExitKey(KEY_NULL);
SetTargetFPS(60);
+
while (!WindowShouldClose()) {
UpdateScene();
BeginDrawing();
DrawScene();
+ DrawFPS(0, 0);
EndDrawing();
}
diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c
index ca2d270..9f607d1 100644
--- a/src/ui_elements/TextEditor.c
+++ b/src/ui_elements/TextEditor.c
@@ -1,3 +1,5 @@
+// TODO: fix j being outside of the box SOME FUCKING HOW
+
#include "UI.h"
#include "../resources/resources.h"
#include <raylib.h>
@@ -19,11 +21,20 @@ TextNode *CreateNode(TextNode *prev, TextNode *next) {
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;
+ node->len = 0;
+ node->text = calloc(DEFAULT_TEXT_NODE_SIZE, sizeof(char));
+ if (node->text != NULL) node->cap = DEFAULT_TEXT_NODE_SIZE;
+ TraceLog(LOG_INFO, "Created a new node");
return node;
}
+void FreeNode(TextNode *node) {
+ if (node == NULL) return;
+ free(node->text);
+ free(node);
+ TraceLog(LOG_INFO, "Deleted a node");
+}
+
/// Recursively frees the nodes
void FreeNodeRec(TextNode *node) {
if (node == NULL) return;
@@ -32,6 +43,37 @@ void FreeNodeRec(TextNode *node) {
free(node);
}
+bool AddSpace(TextNode *base) {
+ TraceLog(LOG_INFO, "Adding space to a node");
+ if (base == NULL) return false;
+ char *new = realloc(base->text, base->cap + DEFAULT_TEXT_NODE_SIZE);
+ if (new == NULL) return false;
+ base->text = new;
+ memset(new + base->cap, 0, DEFAULT_TEXT_NODE_SIZE);
+ base->cap += DEFAULT_TEXT_NODE_SIZE;
+ return true;
+}
+
+bool AddSpaceDetermined(TextNode *base, size_t additional_space) {
+ TraceLog(LOG_INFO, "Adding space to a node");
+ if (base == NULL) return false;
+ char *new = realloc(base->text, base->cap + additional_space);
+ if (new == NULL) return false;
+ base->text = new;
+ memset(new + base->cap, 0, additional_space);
+ base->cap += additional_space;
+ return true;
+}
+void AppendTextToNode(TextNode *base, char *new_text) {
+ if (base == NULL || new_text == NULL) return;
+ size_t len = strlen(base->text);
+ /// >= and not > because it needs a \0
+ if (len + strlen(new_text) >= base->cap) {
+ if (!AddSpace(base)) return;
+ }
+ strcpy(base->text + len, new_text);
+}
+
TextArea *CreateTextArea() {
TextArea *outp = malloc(sizeof(TextArea));
if (outp == NULL) return NULL;
@@ -48,6 +90,45 @@ TextArea *CreateTextArea() {
return outp;
}
+bool PushNode(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return false;
+ TextNode *new_node = CreateNode(ta->CurrentNode, ta->CurrentNode->NextNode);
+ if (new_node == NULL) return false;
+ if (ta->CurrentNode->NextNode != NULL)
+ ((TextNode *)ta->CurrentNode->NextNode)->PrevNode = new_node;
+
+ ta->CurrentNode->NextNode = new_node;
+ ta->NodeLenth += 1;
+ return true;
+}
+
+void PushNodeBefore(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ TextNode *new_node = CreateNode(ta->CurrentNode->PrevNode, ta->CurrentNode);
+ if (new_node == NULL) return;
+ if (ta->CurrentNode->PrevNode != NULL)
+ ((TextNode *)ta->CurrentNode->PrevNode)->NextNode = new_node;
+ if (ta->CurrentNode == ta->StartNode) ta->StartNode = new_node;
+
+ ta->CurrentNode->PrevNode = new_node;
+ ta->NodeLenth += 1;
+}
+
+void PopCurrent(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL || ta->NodeLenth <= 1) return;
+ TextNode *current = ta->CurrentNode;
+ if (current->PrevNode != NULL)
+ ((TextNode *)current->PrevNode)->NextNode = current->NextNode;
+ if (current->NextNode != NULL)
+ ((TextNode *)current->NextNode)->PrevNode = current->PrevNode;
+
+ /// One of those is guaranteed not to be null (hopefully)
+ if (current->PrevNode != NULL) ta->CurrentNode = current->PrevNode;
+ else ta->CurrentNode = current->NextNode;
+ ta->NodeLenth -= 1;
+ FreeNode(current);
+}
+
void FreeTextArea(TextArea *ta) {
FreeNodeRec(ta->StartNode);
free(ta);
@@ -55,20 +136,23 @@ void FreeTextArea(TextArea *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 };
+ Vector2 pos = { .x = rec.x + spacing, .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;
+ pos.y += height;
}
}
void MoveCursorRight(TextArea *ta) {
if (ta == NULL || ta->CurrentNode == NULL) return;
ta->CursorPosition.x += 1;
+
+ size_t line_len = ta->CurrentNode->len;
+ if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
}
void MoveCursorLeft(TextArea *ta) {
@@ -77,18 +161,103 @@ void MoveCursorLeft(TextArea *ta) {
if (ta->CursorPosition.x < 0) ta->CursorPosition.x = 0;
}
+void MoveCursorDown(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ if (ta->CurrentNode->NextNode == NULL) return;
+ ta->CurrentNode = ta->CurrentNode->NextNode;
+
+ ta->CursorPosition.y += 1;
+ size_t line_len = ta->CurrentNode->len;
+ if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
+}
+
+void MoveCursorUp(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ if (ta->CursorPosition.y == 0 || ta->CurrentNode->PrevNode == NULL) return;
+ ta->CurrentNode = ta->CurrentNode->PrevNode;
+ ta->CursorPosition.y -= 1;
+
+ size_t line_len = ta->CurrentNode->len;
+ if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
+}
+
+void BreakLine(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ if (ta->CursorPosition.x == 0) {
+ PushNodeBefore(ta);
+ ta->CursorPosition.y += 1;
+ return;
+ }
+
+ if (!PushNode(ta)) {
+ // Something went wrong, silently undermine
+ TraceLog(LOG_ERROR, "Failed to push a node: the initializator returned NULL");
+ return;
+ }
+
+ size_t current_node_len = strlen(ta->CurrentNode->text);
+ if (ta->CursorPosition.x < current_node_len) {
+ char *after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x);
+ size_t after_str_len = strlen(after_str);
+ if (((TextNode *)ta->CurrentNode->NextNode)->cap < after_str_len) {
+ if (!AddSpaceDetermined(ta->CurrentNode->NextNode, after_str_len)) {
+ TraceLog(LOG_ERROR, "Failed to push a node: the space reservaton failed");
+ }
+ }
+ strcpy(((TextNode *)ta->CurrentNode->NextNode)->text, after_str);
+ ((TextNode *)ta->CurrentNode->NextNode)->len = after_str_len;
+ for (int i = ta->CursorPosition.x; i < current_node_len; i++) {
+ ta->CurrentNode->text[i] = 0x0;
+ }
+ ta->CurrentNode->len -= after_str_len;
+ }
+ ta->CursorPosition.y += 1;
+ ta->CursorPosition.x = 0;
+ ta->CurrentNode = ta->CurrentNode->NextNode;
+}
+
void InsertChar(TextArea *ta, char new_char) {
if (ta == NULL || ta->CurrentNode == NULL) return;
+ size_t line_len = ta->CurrentNode->len;
+
+ if (line_len + 2 > ta->CurrentNode->cap) {
+ /// The reallocation fails
+ if (!AddSpace(ta->CurrentNode)) return;
+ }
+
+ if (ta->CursorPosition.x < line_len) {
+ TraceLog(LOG_INFO, "memcpy");
+ memmove(ta->CurrentNode->text + (int)ta->CursorPosition.x + 1,
+ ta->CurrentNode->text + (int)ta->CursorPosition.x,
+ line_len - ta->CursorPosition.x + 1);
+ } else {
+ (ta->CurrentNode->text)[(int)ta->CursorPosition.x+1] = 0x0;
+ }
+
(ta->CurrentNode->text)[(int)ta->CursorPosition.x] = new_char;
ta->CursorPosition.x += 1;
- size_t line_len = strlen(ta->CurrentNode->text);
+ ta->CurrentNode->len += 1;
+ line_len += 1;
+
if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
}
void DeleteChar(TextArea *ta) {
+ // TODO: Split this function in parts
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 == 0) {
+ if (ta->CursorPosition.y == 0 || ta->CurrentNode->PrevNode == NULL) return;
+ int target_x = strlen(((TextNode *)ta->CurrentNode->PrevNode)->text);
+ // The cursor should remove prevoius line break
+ AppendTextToNode(ta->CurrentNode->PrevNode, ta->CurrentNode->text);
+ PopCurrent(ta);
+ /// The cursor is guaranteed to go up because the y coordinate is > 0
+ ta->CursorPosition.y -= 1;
+ ta->CursorPosition.x = target_x;
+ ta->CurrentNode->len -= 1;
+ return;
+ };
+ size_t line_len = ta->CurrentNode->len;
if (ta->CursorPosition.x == line_len) {
ta->CurrentNode->text[line_len - 1] = 0x0;
@@ -97,10 +266,19 @@ void DeleteChar(TextArea *ta) {
strcpy(ta->CurrentNode->text + (int)ta->CursorPosition.x - 1, after_str);
}
ta->CursorPosition.x -= 1;
+ ta->CurrentNode->len -= 1;
}
bool IsKeyPressedFix(int key) {
- return IsKeyPressedRepeat(key) || IsKeyPressed(key);
+ return IsKeyPressed(key) || IsKeyPressedRepeat(key);
+}
+
+void PrintAllLines(TextArea *ta) {
+ TextNode *node = ta->StartNode;
+ while (node != NULL) {
+ TraceLog(LOG_INFO, "%d\t| %s", node->len, node->text);
+ node = node->NextNode;
+ }
}
void HandleKeyboard(TextArea *ta) {
@@ -113,6 +291,10 @@ void HandleKeyboard(TextArea *ta) {
}
if (IsKeyPressedFix(KEY_BACKSPACE)) DeleteChar(ta);
+ if (IsKeyPressedFix(KEY_ENTER)) BreakLine(ta);
if (IsKeyPressedFix(KEY_LEFT)) MoveCursorLeft(ta);
if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRight(ta);
+ if (IsKeyPressedFix(KEY_DOWN)) MoveCursorDown(ta);
+ if (IsKeyPressedFix(KEY_UP)) MoveCursorUp(ta);
+ if (IsKeyPressedFix(KEY_F3)) PrintAllLines(ta);
}
diff --git a/src/ui_elements/UI.h b/src/ui_elements/UI.h
index 4c94bf7..1029289 100644
--- a/src/ui_elements/UI.h
+++ b/src/ui_elements/UI.h
@@ -10,12 +10,13 @@ float MeasureChar(Font *font, int height, char symbol);
// ========== TEXT EDITOR ==========
-static const size_t DEFAULT_TEXT_NODE_SIZE = 256;
+static const size_t DEFAULT_TEXT_NODE_SIZE = 5;
typedef struct {
void *PrevNode;
void *NextNode;
char *text;
+ size_t len;
size_t cap;
} TextNode;
@@ -37,5 +38,6 @@ void DeleteChar(TextArea *ta);
void HandleKeyboard(TextArea *ta);
void MoveCursorRight(TextArea *ta);
void MoveCursorLeft(TextArea *ta);
+void MoveCursorDown(TextArea *ta);
#endif // UI_ELEMENTS_H