4 #include "edit_field.h"
5 #include "game/sprite_font.h"
6 #include "sdl/renderer.h"
7 #include "system/error.h"
10 #define BUFFER_CAPACITY 256
18 const Sprite_font *font;
25 static void edit_field_left(Edit_field *edit_field);
26 static void edit_field_right(Edit_field *edit_field);
27 static void edit_field_backspace(Edit_field *edit_field);
28 static void edit_field_delete(Edit_field *edit_field);
29 static void edit_field_insert_char(Edit_field *edit_field, char c);
31 static char shift_char(char c)
35 } else if (c == '0') {
37 } else if (c == '=') {
39 } else if (c == '\'') {
46 Edit_field *create_edit_field(const Sprite_font *font,
58 Edit_field *const edit_field = PUSH_LT(lt, malloc(sizeof(Edit_field)), free);
59 if (edit_field == NULL) {
60 throw_error(ERROR_TYPE_LIBC);
65 edit_field->buffer = PUSH_LT(lt, malloc(sizeof(char) * (BUFFER_CAPACITY + 10)), free);
66 if (edit_field->buffer == NULL) {
67 throw_error(ERROR_TYPE_LIBC);
71 edit_field->buffer_size = 0;
72 edit_field->cursor = 0;
73 edit_field->font = font;
74 edit_field->font_size = font_size;
75 edit_field->font_color = font_color;
76 edit_field->shift_key = false;
77 edit_field->focused = false;
79 edit_field->buffer[edit_field->buffer_size] = 0;
84 void destroy_edit_field(Edit_field *edit_field)
87 RETURN_LT0(edit_field->lt);
90 int edit_field_render(const Edit_field *edit_field,
91 SDL_Renderer *renderer,
97 const float cursor_y_overflow = 10.0f;
98 const float cursor_width = 2.0f;
100 if (sprite_font_render_text(edit_field->font,
103 edit_field->font_size,
104 edit_field->font_color,
105 edit_field->buffer) < 0) {
109 /* TODO(#363): the size of the cursor does not correspond to font size */
110 if (edit_field->focused) {
113 rect(position.x + (float) edit_field->cursor * (float) FONT_CHAR_WIDTH * edit_field->font_size.x,
114 position.y - cursor_y_overflow,
116 FONT_CHAR_HEIGHT * edit_field->font_size.y + cursor_y_overflow * 2.0f),
117 edit_field->font_color) < 0) {
125 int edit_field_handle_event(Edit_field *edit_field,
126 const SDL_Event *event)
131 switch (event->type) {
133 switch (event->key.keysym.sym) {
135 edit_field_left(edit_field);
139 edit_field_right(edit_field);
143 edit_field_backspace(edit_field);
148 edit_field->shift_key = true;
152 edit_field_delete(edit_field);
156 edit_field_insert_char(edit_field, (char) event->key.keysym.sym);
162 switch (event->key.keysym.sym) {
165 edit_field->shift_key = false;
178 const char *edit_field_as_text(const Edit_field *edit_field)
181 return edit_field->buffer;
184 static void edit_field_left(Edit_field *edit_field)
186 if (edit_field->cursor > 0) {
187 edit_field->cursor--;
191 static void edit_field_right(Edit_field *edit_field)
194 if (edit_field->cursor < edit_field->buffer_size) {
195 edit_field->cursor++;
199 static void edit_field_backspace(Edit_field *edit_field)
203 if (edit_field->cursor == 0) {
207 for (size_t i = edit_field->cursor; i < edit_field->buffer_size; ++i) {
208 edit_field->buffer[i - 1] = edit_field->buffer[i];
211 edit_field->cursor--;
212 edit_field->buffer[--edit_field->buffer_size] = 0;
215 static void edit_field_delete(Edit_field *edit_field)
219 if (edit_field->cursor >= edit_field->buffer_size) {
223 for (size_t i = edit_field->cursor; i < edit_field->buffer_size; ++i) {
224 edit_field->buffer[i] = edit_field->buffer[i + 1];
227 edit_field->buffer[--edit_field->buffer_size] = 0;
230 static void edit_field_insert_char(Edit_field *edit_field, char c)
234 if (edit_field->shift_key) {
238 if (edit_field->buffer_size >= BUFFER_CAPACITY) {
242 for (int64_t i = (int64_t) edit_field->buffer_size - 1; i >= (int64_t) edit_field->cursor; --i) {
243 edit_field->buffer[i + 1] = edit_field->buffer[i];
246 edit_field->buffer[edit_field->cursor++] = c;
247 edit_field->buffer[++edit_field->buffer_size] = 0;
250 void edit_field_clean(Edit_field *edit_field)
252 edit_field->cursor = 0;
253 edit_field->buffer_size = 0;
254 edit_field->buffer[0] = 0;
257 void edit_field_focus(Edit_field *edit_field)
259 edit_field->focused = true;
262 void edit_field_unfocus(Edit_field *edit_field)
264 edit_field->focused = false;