diff --git a/include/tim.h b/include/tim.h index 09d3502..299e684 100644 --- a/include/tim.h +++ b/include/tim.h @@ -156,6 +156,7 @@ typedef struct TimEvent { } TimEvent; typedef struct TimEditState { + bool masked; // if true prints '*' instead of buffer content i32 cursor; // cursor position (utf8) i32 length; // string length (utf8) i32 capacity; // buffer size in bytes @@ -273,12 +274,21 @@ bool tim_checkbox(cstr txt, i32* state, i32 x, i32 y, i32 w, TimStyle style); bool tim_radiobutton(cstr txt, i32* state, i32 v, i32 x, i32 y, i32 w, TimStyle style); /// text edit - value in state -/// @param e persistent edit state, use TimEditState_init() to create new state +/// @param e persistent edit state, use TimEditState_construct() to create new state /// @param color frame, background, text /// @return key id or 0 TimKey tim_edit(TimEditState* e, i32 x, i32 y, i32 w, TimStyle style); -void TimEditState_init(TimEditState* e, i32 capacity, cstr initial_content); +/// @param e uninitialized state +/// @param capacity in bytes +/// @param initial_content may be NULL +void TimEditState_construct(TimEditState* e, i32 capacity, cstr initial_content); + +static inline void TimEditState_destroy(TimEditState* e) { + if(!e) + return; + free(e->s); +} void TimEditState_insert(TimEditState* e, cstr s); diff --git a/src/edit.c b/src/edit.c index b366443..4212fe1 100755 --- a/src/edit.c +++ b/src/edit.c @@ -1,9 +1,9 @@ #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); +void TimEditState_construct(TimEditState* e, i32 capacity, cstr initial_content){ + e->masked = false; + e->length = initial_content ? tim_utf8_len(initial_content) : 0; + e->cursor = e->length; e->capacity = capacity; e->s = (char*)malloc(capacity + 1); i32 byte_len = strlen(initial_content); @@ -90,13 +90,31 @@ TimKey tim_edit(TimEditState* e, i32 x, i32 y, i32 w, TimStyle style) { if (tim->event.type == TimEvent_Draw) { tim_draw_box(r.x, r.y, r.w, r.h, style.brd, style.bg); - 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, style.fg, style.bg); - 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, style.fg, style.bg); + + i32 s_x = r.x + 2, s_y = r.y + 1, s_w = r.w - 3, s_w_sub1 = s_w - 1; + char* s = e->s; + bool focused = tim->focus == e; + + if (focused) { + // rewind long buffer so cursor is at the most right cell + s = e->s + tim_utf8_pos(e->s, e->cursor - s_w_sub1); + } + + if(e->masked){ + // draw '*' instead of buffer characters + TimCell cell_masked = tim_cell("*", style.fg, style.bg); + i32 w_mask = MIN(s_w, e->length); + tim_draw_row(cell_masked, s_x, s_y, w_mask); + } + else { + // draw part of buffer content + tim_draw_str(s, s_x, s_y, s_w, style.fg, style.bg); + } + + if (focused) { + // invert color of last cell + i32 cur = MIN(s_w_sub1, e->cursor); + tim_draw_invert(s_x + cur, s_y, 1); } } diff --git a/test/test.c b/test/test.c index 60bef7a..1baeb77 100644 --- a/test/test.c +++ b/test/test.c @@ -116,13 +116,18 @@ static inline void test_screen(TimEvent* e) { } i32 main(void) { - TimEditState_init(&ed1, 32, "Edit 1"); - TimEditState_init(&ed2, 32, ""); + TimEditState_construct(&ed1, 32, "Edit 1"); + TimEditState_construct(&ed2, 32, ""); + while (tim_run(1.5)) { test_screen(&tim->event); if (tim_is_key_press('q') || tim_is_key_press(TimKey_Escape)) { break; } } + + TimEditState_destroy(&ed1); + TimEditState_destroy(&ed2); + return 0; }