3 #include "edit_field.h"
4 #include "game/camera.h"
5 #include "game/sprite_font.h"
6 #include "sdl/renderer.h"
8 #include "system/nth_alloc.h"
9 #include "system/stacktrace.h"
11 #define BUFFER_CAPACITY 256
23 static void edit_field_left(Edit_field *edit_field);
24 static void edit_field_right(Edit_field *edit_field);
25 static void edit_field_backspace(Edit_field *edit_field);
26 static void edit_field_delete(Edit_field *edit_field);
27 static void edit_field_insert_char(Edit_field *edit_field, char c);
29 Edit_field *create_edit_field(Vec font_size,
34 Edit_field *const edit_field = PUSH_LT(lt, nth_calloc(1, sizeof(Edit_field)), free);
35 if (edit_field == NULL) {
40 edit_field->buffer = PUSH_LT(lt, nth_calloc(1, sizeof(char) * (BUFFER_CAPACITY + 10)), free);
41 if (edit_field->buffer == NULL) {
45 edit_field->buffer_size = 0;
46 edit_field->cursor = 0;
47 edit_field->font_size = font_size;
48 edit_field->font_color = font_color;
50 edit_field->buffer[edit_field->buffer_size] = 0;
55 void destroy_edit_field(Edit_field *edit_field)
57 trace_assert(edit_field);
58 RETURN_LT0(edit_field->lt);
61 int edit_field_render_screen(const Edit_field *edit_field,
63 Point screen_position)
65 trace_assert(edit_field);
68 const float cursor_y_overflow = 10.0f;
69 const float cursor_width = 2.0f;
71 if (camera_render_text_screen(
74 edit_field->font_size,
75 edit_field->font_color,
76 screen_position) < 0) {
80 /* TODO(#363): the size of the cursor does not correspond to font size */
81 if (camera_fill_rect_screen(
83 rect(screen_position.x + (float) edit_field->cursor * (float) FONT_CHAR_WIDTH * edit_field->font_size.x,
84 screen_position.y - cursor_y_overflow,
86 FONT_CHAR_HEIGHT * edit_field->font_size.y + cursor_y_overflow * 2.0f),
87 edit_field->font_color) < 0) {
94 int edit_field_render_world(const Edit_field *edit_field,
98 trace_assert(edit_field);
101 const float cursor_y_overflow = 10.0f;
102 const float cursor_width = 2.0f;
104 if (camera_render_text(
107 edit_field->font_size,
108 edit_field->font_color,
109 world_position) < 0) {
113 if (camera_fill_rect(
115 rect(world_position.x + (float) edit_field->cursor * (float) FONT_CHAR_WIDTH * edit_field->font_size.x,
116 world_position.y - cursor_y_overflow,
118 FONT_CHAR_HEIGHT * edit_field->font_size.y + cursor_y_overflow * 2.0f),
119 edit_field->font_color) < 0) {
126 const char *edit_field_as_text(const Edit_field *edit_field)
128 trace_assert(edit_field);
129 return edit_field->buffer;
132 static void edit_field_left(Edit_field *edit_field)
134 if (edit_field->cursor > 0) {
135 edit_field->cursor--;
139 static void edit_field_right(Edit_field *edit_field)
141 trace_assert(edit_field);
142 if (edit_field->cursor < edit_field->buffer_size) {
143 edit_field->cursor++;
147 static void edit_field_backspace(Edit_field *edit_field)
149 trace_assert(edit_field);
151 if (edit_field->cursor == 0) {
155 for (size_t i = edit_field->cursor; i < edit_field->buffer_size; ++i) {
156 edit_field->buffer[i - 1] = edit_field->buffer[i];
159 edit_field->cursor--;
160 edit_field->buffer[--edit_field->buffer_size] = 0;
163 static void edit_field_delete(Edit_field *edit_field)
165 trace_assert(edit_field);
167 if (edit_field->cursor >= edit_field->buffer_size) {
171 for (size_t i = edit_field->cursor; i < edit_field->buffer_size; ++i) {
172 edit_field->buffer[i] = edit_field->buffer[i + 1];
175 edit_field->buffer[--edit_field->buffer_size] = 0;
178 static void edit_field_insert_char(Edit_field *edit_field, char c)
180 trace_assert(edit_field);
182 if (edit_field->buffer_size >= BUFFER_CAPACITY) {
186 for (int64_t i = (int64_t) edit_field->buffer_size - 1; i >= (int64_t) edit_field->cursor; --i) {
187 edit_field->buffer[i + 1] = edit_field->buffer[i];
190 edit_field->buffer[edit_field->cursor++] = c;
191 edit_field->buffer[++edit_field->buffer_size] = 0;
194 void edit_field_clean(Edit_field *edit_field)
196 trace_assert(edit_field);
198 edit_field->cursor = 0;
199 edit_field->buffer_size = 0;
200 edit_field->buffer[0] = 0;
203 void edit_field_replace(Edit_field *edit_field, const char *text)
205 trace_assert(edit_field);
207 edit_field_clean(edit_field);
213 size_t n = strlen(text);
214 for (size_t i = 0; i < n; ++i) {
215 edit_field_insert_char(edit_field, text[i]);
219 int edit_field_event(Edit_field *edit_field, const SDL_Event *event)
221 trace_assert(edit_field);
224 switch (event->type) {
226 switch (event->key.keysym.sym) {
228 edit_field_left(edit_field);
232 edit_field_right(edit_field);
236 edit_field_backspace(edit_field);
240 edit_field_delete(edit_field);
245 case SDL_TEXTINPUT: {
246 size_t n = strlen(event->text.text);
247 for (size_t i = 0; i < n; ++i) {
248 edit_field_insert_char(edit_field, event->text.text[i]);