Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 3041fef1c9906536d5561ba0ed736918e20478f5)
+++ uspace/app/bdsh/input.c	(revision ef8bcc6df47519f80b0b59ebb86b4c416a742a7b)
@@ -38,5 +38,4 @@
 #include <vfs/vfs.h>
 #include <errno.h>
-#include <assert.h>
 #include <bool.h>
 
@@ -48,26 +47,5 @@
 #include "exec.h"
 
-#define HISTORY_LEN 10
-
-typedef struct {
-	wchar_t buffer[INPUT_MAX];
-	int col0, row0;
-	int con_cols, con_rows;
-	int nc;
-	int pos;
-
-	char *history[1 + HISTORY_LEN];
-	int hnum;
-	int hpos;
-} tinput_t;
-
-typedef enum {
-	seek_backward = -1,
-	seek_forward = 1
-} seek_dir_t;
-
-static tinput_t tinput;
-
-static char *tinput_read(tinput_t *ti);
+static void read_line(char *, int);
 
 /* Tokenizes input from console, sees if the first word is a built-in, if so
@@ -121,323 +99,52 @@
 }
 
-static void tinput_display_tail(tinput_t *ti, int start, int pad)
-{
-	int i;
-
-	console_goto(fphone(stdout), (ti->col0 + start) % ti->con_cols,
-	    ti->row0 + (ti->col0 + start) / ti->con_cols);
-	printf("%ls", ti->buffer + start);
-	for (i = 0; i < pad; ++i)
-		putchar(' ');
-	fflush(stdout);
-}
-
-static char *tinput_get_str(tinput_t *ti)
-{
-	return wstr_to_astr(ti->buffer);
-}
-
-static void tinput_position_caret(tinput_t *ti)
-{
-	console_goto(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols,
-	    ti->row0 + (ti->col0 + ti->pos) / ti->con_cols);
-}
-
-/** Update row0 in case the screen could have scrolled. */
-static void tinput_update_origin(tinput_t *ti)
-{
-	int width, rows;
-
-	width = ti->col0 + ti->nc;
-	rows = (width / ti->con_cols) + 1;
- 
-	/* Update row0 if the screen scrolled. */
-	if (ti->row0 + rows > ti->con_rows)
-		ti->row0 = ti->con_rows - rows;	
-}
-
-static void tinput_insert_char(tinput_t *ti, wchar_t c)
-{
-	int i;
-	int new_width, new_height;
-
-	if (ti->nc == INPUT_MAX)
-		return;
-
-	new_width = ti->col0 + ti->nc + 1;
-	if (new_width % ti->con_cols == 0) {
-		/* Advancing to new line. */
-		new_height = (new_width / ti->con_cols) + 1;
-		if (new_height >= ti->con_rows)
-			return; /* Disallow text longer than 1 page for now. */
-	}
-
-	for (i = ti->nc; i > ti->pos; --i)
-		ti->buffer[i] = ti->buffer[i - 1];
-
-	ti->buffer[ti->pos] = c;
-	ti->pos += 1;
-	ti->nc += 1;
-	ti->buffer[ti->nc] = '\0';
-
-	tinput_display_tail(ti, ti->pos - 1, 0);
-	tinput_update_origin(ti);
-	tinput_position_caret(ti);
-}
-
-static void tinput_backspace(tinput_t *ti)
-{
-	int i;
-
-	if (ti->pos == 0)
-		return;
-
-	for (i = ti->pos; i < ti->nc; ++i)
-		ti->buffer[i - 1] = ti->buffer[i];
-	ti->pos -= 1;
-	ti->nc -= 1;
-	ti->buffer[ti->nc] = '\0';
-
-	tinput_display_tail(ti, ti->pos, 1);
-	tinput_position_caret(ti);
-}
-
-static void tinput_delete(tinput_t *ti)
-{
-	if (ti->pos == ti->nc)
-		return;
-
-	ti->pos += 1;
-	tinput_backspace(ti);
-}
-
-static void tinput_seek_cell(tinput_t *ti, seek_dir_t dir)
-{
-	if (dir == seek_forward) {
-		if (ti->pos < ti->nc)
-			ti->pos += 1;
-	} else {
-		if (ti->pos > 0)
-			ti->pos -= 1;
-	}
-
-	tinput_position_caret(ti);
-}
-
-static void tinput_seek_word(tinput_t *ti, seek_dir_t dir)
-{
-	if (dir == seek_forward) {
-		if (ti->pos == ti->nc)
-			return;
-
-		while (1) {
-			ti->pos += 1;
-
-			if (ti->pos == ti->nc)
-				break;
-
-			if (ti->buffer[ti->pos - 1] == ' ' &&
-			    ti->buffer[ti->pos] != ' ')
-				break;
-		}
-	} else {
-		if (ti->pos == 0)
-			return;
-
-		while (1) {
-			ti->pos -= 1;
-
-			if (ti->pos == 0)
-				break;
-
-			if (ti->buffer[ti->pos - 1] == ' ' &&
-			    ti->buffer[ti->pos] != ' ')
-				break;
-		}
-
-	}
-
-	tinput_position_caret(ti);
-}
-
-static void tinput_seek_vertical(tinput_t *ti, seek_dir_t dir)
-{
-	if (dir == seek_forward) {
-		if (ti->pos + ti->con_cols <= ti->nc)
-			ti->pos = ti->pos + ti->con_cols;
-	} else {
-		if (ti->pos - ti->con_cols >= 0)
-			ti->pos = ti->pos - ti->con_cols;
-	}
-
-	tinput_position_caret(ti);
-}
-
-static void tinput_seek_max(tinput_t *ti, seek_dir_t dir)
-{
-	if (dir == seek_backward)
-		ti->pos = 0;
-	else
-		ti->pos = ti->nc;
-
-	tinput_position_caret(ti);
-}
-
-static void tinput_history_insert(tinput_t *ti, char *str)
-{
-	int i;
-
-	if (ti->hnum < HISTORY_LEN) {
-		ti->hnum += 1;
-	} else {
-		if (ti->history[HISTORY_LEN] != NULL)
-			free(ti->history[HISTORY_LEN]);
-	}
-
-	for (i = ti->hnum; i > 1; --i)
-		ti->history[i] = ti->history[i - 1];
-
-	ti->history[1] = str_dup(str);
-
-	if (ti->history[0] != NULL) {
-		free(ti->history[0]);
-		ti->history[0] = NULL;
-	}
-}
-
-static void tinput_set_str(tinput_t *ti, char *str)
-{
-	str_to_wstr(ti->buffer, INPUT_MAX, str);
-	ti->nc = wstr_length(ti->buffer);
-	ti->pos = ti->nc;
-}
-
-static void tinput_history_seek(tinput_t *ti, int offs)
-{
-	int pad;
-
-	if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum)
-		return;
-
-	if (ti->history[ti->hpos] != NULL) {
-		free(ti->history[ti->hpos]);
-		ti->history[ti->hpos] = NULL;
-	}
-
-	ti->history[ti->hpos] = tinput_get_str(ti);
-	ti->hpos += offs;
-
-	pad = ti->nc - str_length(ti->history[ti->hpos]);
-	if (pad < 0) pad = 0;
-
-	tinput_set_str(ti, ti->history[ti->hpos]);
-	tinput_display_tail(ti, 0, pad);
-	tinput_update_origin(ti);
-	tinput_position_caret(ti);
-}
-
-static void tinput_init(tinput_t *ti)
-{
-	ti->hnum = 0;
-	ti->hpos = 0;
-	ti->history[0] = NULL;
-}
-
-static char *tinput_read(tinput_t *ti)
+static void read_line(char *buffer, int n)
 {
 	console_event_t ev;
-	char *str;
+	size_t offs, otmp;
+	wchar_t dec;
 
-	fflush(stdout);
-
-	if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
-		return NULL;
-	if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
-		return NULL;
-
-	ti->pos = 0;
-	ti->nc = 0;
-	ti->buffer[0] = '\0';
-
+	offs = 0;
 	while (true) {
 		fflush(stdout);
 		if (!console_get_event(fphone(stdin), &ev))
-			return NULL;
+			return;
 		
 		if (ev.type != KEY_PRESS)
 			continue;
-
-		if ((ev.mods & KM_CTRL) != 0 &&
-		    (ev.mods & (KM_ALT | KM_SHIFT)) == 0) {
-			switch (ev.key) {
-			case KC_LEFT:
-				tinput_seek_word(ti, seek_backward);
-				break;
-			case KC_RIGHT:
-				tinput_seek_word(ti, seek_forward);
-				break;
-			case KC_UP:
-				tinput_seek_vertical(ti, seek_backward);
-				break;
-			case KC_DOWN:
-				tinput_seek_vertical(ti, seek_forward);
-				break;
+		
+		if (ev.key == KC_ENTER || ev.key == KC_NENTER)
+			break;
+		if (ev.key == KC_BACKSPACE) {
+			if (offs > 0) {
+				/*
+				 * Back up until we reach valid start of
+				 * character.
+				 */
+				while (offs > 0) {
+					--offs; otmp = offs;
+					dec = str_decode(buffer, &otmp, n);
+					if (dec != U_SPECIAL)
+						break;
+				}
+				putchar('\b');
 			}
+			continue;
 		}
-
-		if ((ev.mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
-			switch (ev.key) {
-			case KC_ENTER:
-			case KC_NENTER:
-				goto done;
-			case KC_BACKSPACE:
-				tinput_backspace(ti);
-				break;
-			case KC_DELETE:
-				tinput_delete(ti);
-				break;
-			case KC_LEFT:
-				tinput_seek_cell(ti, seek_backward);
-				break;
-			case KC_RIGHT:
-				tinput_seek_cell(ti, seek_forward);
-				break;
-			case KC_HOME:
-				tinput_seek_max(ti, seek_backward);
-				break;
-			case KC_END:
-				tinput_seek_max(ti, seek_forward);
-				break;
-			case KC_UP:
-				tinput_history_seek(ti, +1);
-				break;
-			case KC_DOWN:
-				tinput_history_seek(ti, -1);
-				break;
-			}
-		}
-
 		if (ev.c >= ' ') {
-			tinput_insert_char(ti, ev.c);
+			if (chr_encode(ev.c, buffer, &offs, n - 1) == EOK)
+				putchar(ev.c);
 		}
 	}
-
-done:
-	ti->pos = ti->nc;
-	tinput_position_caret(ti);
 	putchar('\n');
-
-	str = tinput_get_str(ti);
-	if (str_cmp(str, "") != 0)
-		tinput_history_insert(ti, str);
-
-	ti->hpos = 0;
-
-	return str;
+	buffer[offs] = '\0';
 }
 
+/* TODO:
+ * Implement something like editline() / readline(), if even
+ * just for command history and making arrows work. */
 void get_input(cliuser_t *usr)
 {
-	char *str;
+	char line[INPUT_MAX];
 
 	fflush(stdout);
@@ -447,18 +154,11 @@
 	console_set_style(fphone(stdout), STYLE_NORMAL);
 
-	str = tinput_read(&tinput);
+	read_line(line, INPUT_MAX);
+	/* Make sure we don't have rubbish or a C/R happy user */
+	if (str_cmp(line, "") == 0 || str_cmp(line, "\n") == 0)
+		return;
+	usr->line = str_dup(line);
 
-	/* Check for empty input. */
-	if (str_cmp(str, "") == 0) {
-		free(str);
-		return;
-	}
-
-	usr->line = str;
 	return;
 }
 
-void input_init(void)
-{
-	tinput_init(&tinput);
-}
