geadline2(prompt, text) { local capacity = 64, size = 0, i = 0, c, a, buf; if (text) { size = strlen(text); i = size; loop { if (capacity > size) break; capacity = capacity * 2; } buf = galloc(capacity); if (buf == NULL) return NULL; strcpy(buf, text); } else { buf = galloc(capacity); if (buf == NULL) return NULL; [buf] = 0; } if (prompt) putstr(prompt); putstr(buf); loop { c = getchar(); if ((c == 0xffff) | (c == 0x04)) { if ((size == 0) | (c == 0xffff)) { free(buf); return 0; } } else if (c == 0x1b) { // ESC code getchar(); // skip [ c = getchar(); // value if ((c == 'A') & (size > 0)) { loop { if (i == 0) break; i = i - 1; esccode('D'); } } else if ((c == 'B') & (i < size)) { loop { if (i >= size) break; i = i + 1; esccode('C'); } } else if ((c == 'C') & (i < size)) { i = i + 1; esccode('C'); } else if ((c == 'D') & (i > 0)) { i = i - 1; esccode('D'); } wrt '\a'; } else if (c == 0x7f) { if (i) { a = i - 1; loop { if (a >= size) break; [buf + a] = [buf + a + 1]; a = a + 1; } size = size - 1; i = i - 1; [buf + size] = 0; wrt '\r'; if (prompt) putstr(prompt); putstr(buf); wrt ' '; esccode('D'); a = size - i; loop { if (a == 0) break; a = a - 1; esccode('D'); } } } else { size = size + 1; if (size >= capacity) { buf = realloc(buf, capacity * 2); if (buf == NULL) return NULL; capacity = capacity * 2; } a = size - i - 1; loop { if ((a == 0xffff) | (a == 0)) break; [buf + i + a] = [buf + i + a - 1]; a = a - 1; } [buf + i] = c; [buf + size] = 0; putstr(buf + i); a = strlen(buf + i) - 1; loop { if ((a == 0xffff) | (a == 0)) break; a = a - 1; esccode('D'); } i = i + 1; if (c == '\n') return buf; } } } geadline(prompt) { geadline2(prompt, NULL); } esccode(c) { wrt 0x1b; wrt '['; wrt c; }