#include <readline.h>
#include <stdlib.h>
char* freadln(FILE f) {
fprint(f, "\x1b[e"); // enable keyboard echo
int i;
char *p = (char*)malloc(256);
char *b = p;
while (1) {
int l = read(f, 0, 255, b);
if (l < 0) {
free(b);
return 0;
}
for (i = 0; i < l; i++) {
if (b[i] == '\n') {
b[i+1] = 0;
return p;
} else if (b[i] == 27) { // ignore escape sequences
b[i] = 0;
l = i;
}
}
int d = b - p + l;
char* newp = (char*)malloc(d + 256);
memcpy(newp, p, d);
free(p);
p = newp;
b = p + d;
}
}
char* readln() {
return freadln(term);
}
// ** READLINE
char *freadline(FILE f, readline_history *h) {
int i;
fprint(f, "\x1b[h"); // disable keyboard echo
if (h->str == 0) {
h->str = (char**)malloc(h->max * sizeof(char*));
for (i = 0; i < h->max; i++) h->str[i] = 0;
h->n = 0;
}
int lid;
if (h->n < h->max) {
lid = h->n++;
} else {
free(h->str[0]);
int i;
for (i = 0; i < h->max - 1; i++) {
h->str[i] = h->str[i+1];
}
lid = h->max - 1;
h->str[lid] = 0;
}
if (h->str[lid] == 0) h->str[lid] = (char*)malloc(256);
char *str = h->str[lid];
str[0] = 0;
char *cur = str; // position in string
int len = 0; // string length
while (1) {
int finished = 0;
int te = cur - str;
char buf[16];
int l = read(f, 0, 16, buf);
if (l < 0) return 0;
char *in = buf;
while (in < buf + l) {
if (*in == 27) {
in++;
if (*in == '[') {
in++;
if (*in == 'A') { // up
if (lid > 0) {
lid--;
str = h->str[lid];
len = strlen(str);
cur = str + len;
}
} else if (*in == 'B') { // down
if (lid < h->n - 1) {
lid++;
str = h->str[lid];
len = strlen(str);
cur = str + len;
}
} else if (*in == 'C') { // forward (right)
if (cur < str + len) cur++;
} else if (*in == 'D') { // back (left)
if (cur > str) cur--;
}
} else {
// ALT sequence - ignore
in++;
}
} else if (*in == '\n') {
finished = 1;
cur = str + len;
} else if (*in == '\b') {
if (cur > str) {
cur--;
len--;
char* c;
for (c = cur; *c != 0; c++) c[0] = c[1];
}
} else if (*in == '\t') {
// ignore tabs -- todo: tab completion???? haha
} else if (*in >= ' ') {
if (l < 255) {
char* c;
for (c = cur + len; c >= cur; c--) c[1] = c[0];
cur[0] = *in;
cur++;
len++;
}
}
in++;
}
// ASSUMPTION : everything will fit on one line...
if (te > 0) fprintf(f, "\x1b[%iD", te);
fprintf(f, "\x1b[K%s", str);
te = len - (cur - str);
if (te > 0) fprintf(f, "\x1b[%iD", te);
if (finished) {
fprintf(f, "\n");
if (h->str[h->n-1] != str) h->n--;
i = h->n - 1;
while (h->str[i] != str) {
if (i == 0) {
fprint(f, "READLINE FAIL");
return 0;
}
i--;
}
while (i < h->n - 1) {
h->str[i] = h->str[i+1];
i++;
}
h->str[i] = str;
if (h->str[h->n-1][0] == 0) h->n--;
return str;
}
}
}