#include "tim.h" void TimEditState_init(TimEditState* e, i32 capacity, cstr initial_content){ e->length = tim_utf8_len(initial_content); e->cursor = tim_utf8_len(initial_content); e->capacity = capacity; e->s = (char*)malloc(capacity + 1); i32 byte_len = strlen(initial_content); memcpy(e->s, initial_content, byte_len); e->s[byte_len] = 0; } void TimEditState_insert(TimEditState* e, cstr s) { i32 dst_size = tim_ztrlen(e->s); i32 src_size = tim_ztrlen(s); if (dst_size + src_size < e->capacity) { i32 len = tim_utf8_len(s); // usually 1, except when smashing keys i32 cur = tim_utf8_pos(e->s, e->cursor); memmove(e->s + cur + src_size, e->s + cur, dst_size - cur); memmove(e->s + cur, s, src_size); e->s[dst_size + src_size] = 0; e->length += len; e->cursor += len; } } void TimEditState_delete(TimEditState* e) { i32 size = tim_ztrlen(e->s); i32 cur = tim_utf8_pos(e->s, e->cursor); i32 len = tim_utf8_pos(e->s + cur, 1); if (size - cur > 0) { memmove(e->s + cur, e->s + cur + len, size - cur); e->length -= 1; } } /// @return key id or 0 static TimKey edit_event(TimEditState* e, TimRect r) { if (tim_is_mouse_click_over(r)) { // take focus tim->focus = e; return 0; } if (tim->focus != e || tim->event.type != TimEvent_Key) { // not focused or no key press return 0; } tim->event.type = TimEvent_Void; // consume event switch (tim->event.key) { case TimKey_Escape: case TimKey_Enter: tim->focus = 0; // release focus break; case TimKey_Delete: TimEditState_delete(e); break; case TimKey_Backspace: if (e->cursor > 0) { e->cursor -= 1; TimEditState_delete(e); } break; case TimKey_Left: e->cursor -= (e->cursor > 0); break; case TimKey_Right: e->cursor += (e->cursor < e->length); break; case TimKey_Home: e->cursor = 0; break; case TimKey_End: e->cursor = e->length; break; default: if (tim->event.key >= ' ') { TimEditState_insert(e, tim->event.s); } break; } return tim->event.key; } TimKey tim_edit(TimEditState* e, i32 x, i32 y, i32 w, u64 color) { TimRect r = tim_scope_rect_to_absolute(x, y, w, 3); if (tim->event.type == TimEvent_Draw) { tim_draw_box(r.x, r.y, r.w, r.h, color >> 16, color >> 8); if (tim->focus == e) { char* s = e->s + tim_utf8_pos(e->s, e->cursor - r.w + 4); i32 cur = MIN(r.w - 4, e->cursor); tim_draw_str(s, r.x + 2, r.y + 1, r.w - 3, color, color >> 8); tim_draw_invert(r.x + cur + 2, r.y + 1, 1); } else { tim_draw_str(e->s, r.x + 2, r.y + 1, r.w - 3, color, color >> 8); } } return edit_event(e, r); }