1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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);
}
|