summaryrefslogtreecommitdiff
path: root/src/ui_elements/TextEditor.c
diff options
context:
space:
mode:
authorphysick <mynameisgennadiy@vk.com>2026-07-30 14:19:45 +0500
committerphysick <mynameisgennadiy@vk.com>2026-07-30 14:19:45 +0500
commitd56f4859c06d184f294cf4d73e7c1068db245809 (patch)
tree517105cf9e3b9c89610f3cd7acfeefb5024ef1a0 /src/ui_elements/TextEditor.c
parent7237c999918e44e2e76a6d2e2ae37ea709af08f6 (diff)
Mouse cursor movements
Diffstat (limited to 'src/ui_elements/TextEditor.c')
-rw-r--r--src/ui_elements/TextEditor.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c
index e114080..13401d8 100644
--- a/src/ui_elements/TextEditor.c
+++ b/src/ui_elements/TextEditor.c
@@ -5,6 +5,7 @@
#include "../resources/resources.h"
#include <ctype.h>
#include <raylib.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -22,6 +23,30 @@ float GetCursorXPos(TextArea *ta) {
return x_position;
}
+// Returns the position the cursor should be in on the given offset.
+size_t GetCharIdxByOffset(TextArea *ta, int line, float offset) {
+ if (ta == NULL) return 0;
+ TextNode *node = ta->StartNode;
+ for (int i = 0; i < line; i++) {
+ node = node->NextNode;
+ if (node == NULL) return 0;
+ }
+
+ for (int i = 0; i < node->len; i++) {
+ char original_char = node->text[i + 1];
+ node->text[i + 1] = '\0';
+
+ float width = MeasureTextEx(*ta->DisplayParams->font,
+ node->text,
+ ta->DisplayParams->font_size,
+ ta->DisplayParams->spacing).x;
+
+ node->text[i + 1] = original_char;
+ if (width > offset) return i;
+ }
+ return node->len;
+}
+
/// We pass x_position not to call GetCursorXPos twice (it's expencive)
void DrawCursor(TextArea *ta, Vector2 lineStartPos, float x_position) {
DrawLine(lineStartPos.x + x_position, lineStartPos.y,
@@ -284,6 +309,31 @@ void MoveCursorHome(TextArea *ta) {
ta->CursorPosition.x = 0;
}
+// Moves cursor to the position
+void MoveCursorTo(TextArea *ta, int x, int y) {
+ // Making sure we are in bounds
+ if (y >= ta->NodeLenth) y = ta->NodeLenth - 1;
+ if (y < 0) y = 0;
+ if (x < 0) x = 0;
+
+ if (ta->CursorPosition.y < y) {
+ int diff = y - ta->CursorPosition.y;
+ for (int i = 0; i < diff; i++) {
+ ta->CurrentNode = ta->CurrentNode->NextNode;
+ }
+ } else if (ta->CursorPosition.y > y) {
+ int diff = ta->CursorPosition.y - y;
+ for (int i = 0; i < diff; i++) {
+ ta->CurrentNode = ta->CurrentNode->PrevNode;
+ }
+ }
+
+ ta->CursorPosition.y = y;
+ // We could't make sure that was the case before
+ if (x > ta->CurrentNode->len) x = ta->CurrentNode->len;
+ ta->CursorPosition.x = x;
+}
+
size_t GetStartingSpaces(char *string) {
if (string == NULL) return 0;
size_t idx = 0, len = strlen(string);
@@ -479,6 +529,16 @@ void PrintAllLines(TextArea *ta) {
}
}
+/// Returns the position on the text field excluding onscreen offset and scroll
+Vector2 absolutePosToTextPos(TextArea *ta, Rectangle *rec, Vector2 pos) {
+ if (ta == NULL || ta->DisplayParams == NULL || rec == NULL)
+ return (Vector2){0, 0};
+ return (Vector2) {
+ .x = pos.x - rec->x + ta->DisplayParams->scroll_h,
+ .y = pos.y - rec->y + ta->DisplayParams->scroll_v,
+ };
+}
+
/// Assumes that control is pressed
void HandleControlComands(TextArea *ta) {
if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRightWord(ta);
@@ -563,19 +623,34 @@ void HandleScroll(TextArea *ta, Rectangle rec) {
// lazy eval caching
} else {
int text_height = ta->NodeLenth * ta->DisplayParams->font_size;
- int max_scroll = text_height - rec.height;
+ int max_scroll = text_height - ta->DisplayParams->font_size * 2;
ta->DisplayParams->scroll_v -= scroll;
if (ta->DisplayParams->scroll_v < 0)
ta->DisplayParams->scroll_v = 0;
- if (text_height > rec.height && ta->DisplayParams->scroll_v > max_scroll)
+ if (max_scroll > 0 && ta->DisplayParams->scroll_v > max_scroll)
ta->DisplayParams->scroll_v = max_scroll;
}
}
+void HandleMouseEvents(TextArea *ta, Rectangle *rec) {
+ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
+ Vector2 mousePos = GetMousePosition();
+ Vector2 onTextPos = absolutePosToTextPos(ta, rec, mousePos);
+ int cursorLine = (int)(onTextPos.y / ta->DisplayParams->font_size);
+ size_t cursorChar = GetCharIdxByOffset(ta, cursorLine, onTextPos.x);
+ // TraceLog(LOG_INFO, "Mouse pos: { %d; %d }", (int)mousePos.x, (int)mousePos.y);
+ // TraceLog(LOG_INFO, "OnScreen pos: { %d; %d }", (int)onTextPos.x, (int)onTextPos.y);
+ // TraceLog(LOG_INFO, "Line: %d", cursorLine);
+ // TraceLog(LOG_INFO, "Char: %zu", cursorChar);
+ MoveCursorTo(ta, cursorChar, cursorLine);
+ }
+}
+
void UpdateTextArea(TextArea *ta, Rectangle rec) {
HandleKeyboard(ta);
if (IsMouseInRec(rec)) {
HandleScroll(ta, rec);
+ HandleMouseEvents(ta, &rec);
}
}