#include #include #include #include //returns length of string without null terminator //max_length doesn't include null terminator uint32_t read_line(char *sz, uint32_t max_length, const char *prompt) { term_add_sz(prompt); term_add_char(' '); term_paint(); uint32_t l = 0; uint32_t c = 0; while (1) { struct key_packet kp = term_get_key_blocking(); switch (kp.key_id) { case KEY_LEFT_ARROW: if (c) { --c; term_cursor_left(); term_paint(); } continue; case KEY_RIGHT_ARROW: if (c != l) { ++c; term_cursor_right(); term_paint(); } continue; case KEY_HOME: while (c) { --c; term_cursor_left(); } term_paint(); continue; case KEY_END: while (c != l) { ++c; term_cursor_right(); } term_paint(); continue; case KEY_DELETE: if (c != l) { ++c; term_cursor_right(); } case KEY_BSPACE: if (!c) continue; --c; --l; for (uint32_t i = c; i < l; ++i) sz[i] = sz[i + 1]; term_cursor_left(); term_add_sn_no_ww(sz + c, l - c); term_add_char(' '); for (uint32_t i = l + 1; i > c; --i) term_cursor_left(); term_paint(); continue; case KEY_ENTER: while (c != l) { ++c; term_cursor_right(); } sz[l] = '\0'; term_add_char('\n'); term_paint(); _yield_task(); return l; default: if (l == max_length) continue; char ch = key_to_char(kp); if (!ch) continue; if (c == l) { ++l; term_add_char(sz[c++] = ch); term_paint(); continue; } if (!(kp.modifiers & INSERT)) { term_add_char(sz[c++] = ch); term_paint(); continue; } for (uint32_t i = l; i > c; --i) sz[i] = sz[i - 1]; sz[c] = ch; ++l; term_add_sn_no_ww(sz + c, l - c); ++c; for (uint32_t i = l; i > c; --i) term_cursor_left(); term_paint(); continue; } } }