Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision b60c582d0cf4f0476a720c8e05bd742fbffc87ce)
+++ kernel/generic/src/console/kconsole.c	(revision c8bf88d737f715dd3bf256ec6f8bf31e0d3be7e1)
@@ -260,8 +260,8 @@
 			
 			if (wstr_remove(current, position - 1)) {
+				position--;
 				putchar('\b');
-				printf("%ls", current + position);
-				position--;
-				print_cc('\b', wstr_length(current) - position);
+				printf("%ls ", current + position);
+				print_cc('\b', wstr_length(current) - position + 1);
 				continue;
 			}
@@ -334,63 +334,67 @@
 		}
 		
-		if (ch == 0x1b) {
-			/* Special command */
-			wchar_t mod = _getc(indev);
-			wchar_t ch = _getc(indev);
-			
-			if ((mod != 0x5b) && (mod != 0x4f))
+		if (ch == U_LEFT_ARROW) {
+			/* Left */
+			if (position > 0) {
+				putchar('\b');
+				position--;
+			}
+			continue;
+		}
+		
+		if (ch == U_RIGHT_ARROW) {
+			/* Right */
+			if (position < wstr_length(current)) {
+				putchar(current[position]);
+				position++;
+			}
+			continue;
+		}
+		
+		if ((ch == U_UP_ARROW) || (ch == U_DOWN_ARROW)) {
+			/* Up, down */
+			print_cc('\b', position);
+			print_cc(' ', wstr_length(current));
+			print_cc('\b', wstr_length(current));
+			
+			if (ch == U_UP_ARROW) {
+				/* Up */
+				if (history_pos == 0)
+					history_pos = KCONSOLE_HISTORY - 1;
+				else
+					history_pos--;
+			} else {
+				/* Down */
+				history_pos++;
+				history_pos = history_pos % KCONSOLE_HISTORY;
+			}
+			current = history[history_pos];
+			printf("%ls", current);
+			position = wstr_length(current);
+			continue;
+		}
+		
+		if (ch == U_HOME_ARROW) {
+			/* Home */
+			print_cc('\b', position);
+			position = 0;
+			continue;
+		}
+		
+		if (ch == U_END_ARROW) {
+			/* End */
+			printf("%ls", current + position);
+			position = wstr_length(current);
+			continue;
+		}
+		
+		if (ch == U_DELETE) {
+			/* Delete */
+			if (position == wstr_length(current))
 				continue;
 			
-			if ((ch == 0x33) && (_getc(indev) == 0x7e)) {
-				/* Delete */
-				if (position == wstr_length(current))
-					continue;
-				
-				if (wstr_remove(current, position)) {
-					putchar('\b');
-					printf("%ls", current + position);
-					position--;
-					print_cc('\b', wstr_length(current) - position);
-				}
-			} else if (ch == 0x48) {
-				/* Home */
-				print_cc('\b', position);
-				position = 0;
-			} else if (ch == 0x46) {
-				/* End */
-				printf("%ls", current + position);
-				position = wstr_length(current);
-			} else if (ch == 0x44) {
-				/* Left */
-				if (position > 0) {
-					putchar('\b');
-					position--;
-				}
-			} else if (ch == 0x43) {
-				/* Right */
-				if (position < wstr_length(current)) {
-					putchar(current[position]);
-					position++;
-				}
-			} else if ((ch == 0x41) || (ch == 0x42)) {
-				/* Up, down */
-				print_cc('\b', position);
-				print_cc(' ', wstr_length(current));
-				print_cc('\b', wstr_length(current));
-				
-				if (ch == 0x41) {
-					/* Up */
-					if (history_pos == 0)
-						history_pos = KCONSOLE_HISTORY - 1;
-					else
-						history_pos--;
-				} else {
-					/* Down */
-					history_pos++;
-					history_pos = history_pos % KCONSOLE_HISTORY;
-				}
-				current = history[history_pos];
-				printf("%ls", current);
-				position = wstr_length(current);
+			if (wstr_remove(current, position)) {
+				printf("%ls ", current + position);
+				print_cc('\b', wstr_length(current) - position + 1);
 			}
 			continue;
Index: kernel/generic/src/lib/string.c
===================================================================
--- kernel/generic/src/lib/string.c	(revision b60c582d0cf4f0476a720c8e05bd742fbffc87ce)
+++ kernel/generic/src/lib/string.c	(revision c8bf88d737f715dd3bf256ec6f8bf31e0d3be7e1)
@@ -110,6 +110,4 @@
 #include <align.h>
 
-char invalch = '?';
-
 /** Byte mask consisting of lowest @n bits (out of 8) */
 #define LO_MASK_8(n)  ((uint8_t) ((1 << (n)) - 1))
@@ -135,5 +133,5 @@
  * @param size   Size of the string (in bytes).
  *
- * @return Value of decoded character, invalch on decoding error or
+ * @return Value of decoded character, U_SPECIAL on decoding error or
  *         NULL if attempt to decode beyond @a size.
  *
@@ -170,9 +168,9 @@
 	} else {
 		/* 10xxxxxx -- unexpected continuation byte */
-		return invalch;
+		return U_SPECIAL;
 	}
 	
 	if (*offset + cbytes > size)
-		return invalch;
+		return U_SPECIAL;
 	
 	wchar_t ch = b0 & LO_MASK_8(b0_bits);
@@ -184,5 +182,5 @@
 		/* Must be 10xxxxxx */
 		if ((b & 0xc0) != 0x80)
-			return invalch;
+			return U_SPECIAL;
 		
 		/* Shift data bits to ch */
Index: kernel/generic/src/printf/printf_core.c
===================================================================
--- kernel/generic/src/printf/printf_core.c	(revision b60c582d0cf4f0476a720c8e05bd742fbffc87ce)
+++ kernel/generic/src/printf/printf_core.c	(revision c8bf88d737f715dd3bf256ec6f8bf31e0d3be7e1)
@@ -82,4 +82,5 @@
 static char digits_small[] = "0123456789abcdef";
 static char digits_big[] = "0123456789ABCDEF";
+static char invalch = U_SPECIAL;
 
 /** Print one or more characters without adding newline.
