summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-07-09 13:56:13 +0500
committerPhysick <96335032+DegustatorPonos@users.noreply.github.com>2026-07-10 00:04:44 +0500
commit90988da0bdae2c56366abb01f402a0cd34279143 (patch)
treea8bc34825fe72ef206bdfd321479f7a6060dceb7 /src
parentb5140b780170bc4d6f2e6ed9a50319f9165b0a77 (diff)
QOL changes + some emacs-like movements
Diffstat (limited to 'src')
-rw-r--r--src/scenes/puzzleScene.c3
-rw-r--r--src/ui_elements/TextEditor.c134
-rw-r--r--src/ui_elements/UI.c1
-rw-r--r--src/ui_elements/UI.h7
4 files changed, 124 insertions, 21 deletions
diff --git a/src/scenes/puzzleScene.c b/src/scenes/puzzleScene.c
index fb45c02..8824a09 100644
--- a/src/scenes/puzzleScene.c
+++ b/src/scenes/puzzleScene.c
@@ -8,6 +8,7 @@ typedef struct {
Puzzle *PuzzlePtr;
TextArea *EditorInfo;
int scroll;
+ int editor_scroll;
} puzzleSceneData;
const int HEADER_FONT_SIZE = 50;
@@ -73,7 +74,7 @@ bool drawPuzzleScene(void *self) {
DrawTextInRec(pane1, data->PuzzlePtr->Description,
GetMainFont(), 20, COLORSCHEME_BROWN, 3, &data->scroll);
- DrawTextArea(data->EditorInfo, pane2, GetMainFont(), 20, 2);
+ DrawTextArea(data->EditorInfo, pane2, GetMainFont(), 20, 2, &data->editor_scroll);
return true;
}
diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c
index 9f607d1..ebc8671 100644
--- a/src/ui_elements/TextEditor.c
+++ b/src/ui_elements/TextEditor.c
@@ -2,6 +2,7 @@
#include "UI.h"
#include "../resources/resources.h"
+#include <ctype.h>
#include <raylib.h>
#include <stdlib.h>
#include <string.h>
@@ -13,7 +14,7 @@ void HighlightCharacter(Vector2 lineStartPos, char *line, int index, Font *font,
x_position += spacing;
}
DrawLine(lineStartPos.x + x_position, lineStartPos.y,
- lineStartPos.x + x_position, lineStartPos.y + height, COLORSCHEME_ORANGE);
+ lineStartPos.x + x_position, lineStartPos.y + height, COLORSCHEME_BROWN);
}
TextNode *CreateNode(TextNode *prev, TextNode *next) {
@@ -117,7 +118,7 @@ void PushNodeBefore(TextArea *ta) {
void PopCurrent(TextArea *ta) {
if (ta == NULL || ta->CurrentNode == NULL || ta->NodeLenth <= 1) return;
TextNode *current = ta->CurrentNode;
- if (current->PrevNode != NULL)
+ if (current->PrevNode != NULL)
((TextNode *)current->PrevNode)->NextNode = current->NextNode;
if (current->NextNode != NULL)
((TextNode *)current->NextNode)->PrevNode = current->PrevNode;
@@ -134,17 +135,15 @@ void FreeTextArea(TextArea *ta) {
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 + 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.y += height;
- }
+/// Returns a char the cursor is at
+char GetCurrentChar(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return 0x0;
+ return ta->CurrentNode->text[(int)ta->CursorPosition.x];
+}
+
+/// This function is used in the skips through words (<C-arrows>)
+bool IsSkippable(char c) {
+ return isalpha(c) || isdigit(c);
}
void MoveCursorRight(TextArea *ta) {
@@ -155,12 +154,42 @@ void MoveCursorRight(TextArea *ta) {
if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
}
+void MoveCursorRightWord(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ do {
+ ta->CursorPosition.x += 1;
+ } while (IsSkippable(GetCurrentChar(ta)));
+
+ size_t line_len = ta->CurrentNode->len;
+ if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
+}
+
+void MoveCursorEnd(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ ta->CursorPosition.x = ta->CurrentNode->len;
+}
+
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 MoveCursorLeftWord(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ do {
+ ta->CursorPosition.x -= 1;
+ } while (IsSkippable(GetCurrentChar(ta)) && ta->CursorPosition.x > 0);
+
+ size_t line_len = ta->CurrentNode->len;
+ if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len;
+}
+
+void MoveCursorHome(TextArea *ta) {
+ if (ta == NULL || ta->CurrentNode == NULL) return;
+ ta->CursorPosition.x = 0;
+}
+
void MoveCursorDown(TextArea *ta) {
if (ta == NULL || ta->CurrentNode == NULL) return;
if (ta->CurrentNode->NextNode == NULL) return;
@@ -226,10 +255,10 @@ void InsertChar(TextArea *ta, char new_char) {
}
if (ta->CursorPosition.x < line_len) {
- TraceLog(LOG_INFO, "memcpy");
+ // 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);
+ line_len - (int)ta->CursorPosition.x + 1);
} else {
(ta->CurrentNode->text)[(int)ta->CursorPosition.x+1] = 0x0;
}
@@ -246,7 +275,7 @@ void DeleteChar(TextArea *ta) {
// TODO: Split this function in parts
if (ta == NULL || ta->CurrentNode == NULL) return;
if (ta->CursorPosition.x == 0) {
- if (ta->CursorPosition.y == 0 || ta->CurrentNode->PrevNode == NULL) return;
+ 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);
@@ -254,7 +283,8 @@ void DeleteChar(TextArea *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;
+ // ta->CurrentNode->len -= 1;
+ if (ta->CurrentNode->len < 0) ta->CurrentNode->len = 0;
return;
};
size_t line_len = ta->CurrentNode->len;
@@ -267,6 +297,7 @@ void DeleteChar(TextArea *ta) {
}
ta->CursorPosition.x -= 1;
ta->CurrentNode->len -= 1;
+ if (ta->CurrentNode->len < 0) ta->CurrentNode->len = 0;
}
bool IsKeyPressedFix(int key) {
@@ -274,6 +305,9 @@ bool IsKeyPressedFix(int key) {
}
void PrintAllLines(TextArea *ta) {
+ TraceLog(LOG_INFO, "Cursor: %dx%d",
+ (int)ta->CursorPosition.x,
+ (int)ta->CursorPosition.y);
TextNode *node = ta->StartNode;
while (node != NULL) {
TraceLog(LOG_INFO, "%d\t| %s", node->len, node->text);
@@ -281,7 +315,44 @@ void PrintAllLines(TextArea *ta) {
}
}
+/// Assumes that control is pressed
+void HandleControlComands(TextArea *ta) {
+ if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRightWord(ta);
+ if (IsKeyPressedFix(KEY_LEFT)) MoveCursorLeftWord(ta);
+
+ // emacs-like stuff
+ if (IsKeyPressedFix(KEY_F)) MoveCursorRight(ta);
+ if (IsKeyPressedFix(KEY_B)) MoveCursorLeft(ta);
+ if (IsKeyPressedFix(KEY_N)) MoveCursorDown(ta);
+ if (IsKeyPressedFix(KEY_P)) MoveCursorUp(ta);
+ if (IsKeyPressedFix(KEY_A)) MoveCursorHome(ta);
+ if (IsKeyPressedFix(KEY_E)) MoveCursorEnd(ta);
+ if (IsKeyPressedFix(KEY_O)) {
+ BreakLine(ta);
+ MoveCursorUp(ta);
+ MoveCursorEnd(ta);
+ };
+}
+/// Assumes that control is pressed
+void HandleAltComands(TextArea *ta) {
+
+ // emacs-like stuff
+ if (IsKeyPressedFix(KEY_F)) MoveCursorRightWord(ta);
+ if (IsKeyPressedFix(KEY_B)) MoveCursorLeftWord(ta);
+}
+
+
void HandleKeyboard(TextArea *ta) {
+ if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) {
+ HandleControlComands(ta);
+ return;
+ }
+
+ if (IsKeyDown(KEY_LEFT_ALT) || IsKeyDown(KEY_RIGHT_ALT)) {
+ HandleAltComands(ta);
+ return;
+ }
+
int charKey = GetCharPressed();
while (charKey > 0) {
if (charKey >= 32 && charKey <= 125) {
@@ -296,5 +367,34 @@ void HandleKeyboard(TextArea *ta) {
if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRight(ta);
if (IsKeyPressedFix(KEY_DOWN)) MoveCursorDown(ta);
if (IsKeyPressedFix(KEY_UP)) MoveCursorUp(ta);
+
+ if (IsKeyPressedFix(KEY_HOME)) MoveCursorHome(ta);
+ if (IsKeyPressedFix(KEY_END)) MoveCursorEnd(ta);
+
if (IsKeyPressedFix(KEY_F3)) PrintAllLines(ta);
}
+
+/// draws a text area on the screen. Main draw entry point
+void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing, int *scroll) {
+ int vertical_acc = rec.y - *scroll;
+ int text_height = ta->NodeLenth * height;
+ int max_scroll = text_height - rec.height;
+
+ if (text_height >= rec.height && IsMouseInRec(rec)) {
+ *scroll -= GetMouseWheelMove() * SCROLL_SENC;
+ if (*scroll < 0) *scroll = 0;
+ if (*scroll > max_scroll) *scroll = max_scroll;
+ }
+
+ Vector2 pos = { .x = rec.x + spacing, .y = rec.y - *scroll };
+ TextNode *node = ta->StartNode;
+ BeginScissorMode(rec.x, rec.y, rec.width, rec.height);
+ 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.y += height;
+ }
+ EndScissorMode();
+}
diff --git a/src/ui_elements/UI.c b/src/ui_elements/UI.c
index 139f746..a9ab498 100644
--- a/src/ui_elements/UI.c
+++ b/src/ui_elements/UI.c
@@ -3,7 +3,6 @@
const int MAX_LINES = 256;
const int SPACING_H = 1;
-const float SCROLL_SENC = 10;
void DrawRecBordered(Rectangle rec, Color bg, Color border_color, int border_width) {
DrawRectangleRounded(rec, 0.015f, 8, bg);
diff --git a/src/ui_elements/UI.h b/src/ui_elements/UI.h
index 1029289..779290f 100644
--- a/src/ui_elements/UI.h
+++ b/src/ui_elements/UI.h
@@ -4,13 +4,16 @@
#ifndef UI_ELEMENTS_H
#define UI_ELEMENTS_H
+static const float SCROLL_SENC = 10;
+
void DrawRecBordered(Rectangle rec, Color bg, Color border_color, int border_width);
void DrawTextInRec(Rectangle rec, char *text, Font *font, int height, Color color, float padding, int *scroll);
float MeasureChar(Font *font, int height, char symbol);
+bool IsMouseInRec(Rectangle rec);
// ========== TEXT EDITOR ==========
-static const size_t DEFAULT_TEXT_NODE_SIZE = 5;
+static const size_t DEFAULT_TEXT_NODE_SIZE = 256;
typedef struct {
void *PrevNode;
@@ -31,7 +34,7 @@ typedef struct {
TextArea *CreateTextArea();
void FreeTextArea(TextArea *ta);
-void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing);
+void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing, int *scroll);
void InsertChar(TextArea *ta, char new_char);
void DeleteChar(TextArea *ta);