lineedit: first shot at optional unicode bidi input support

function                                             old     new   delta
read_line_input                                     4886    5003    +117
in_uint16_table                                        -      97     +97
in_interval_table                                      -      78     +78
static.rtl_b                                           -      68     +68
unicode_isrtl                                          -      55     +55
isrtl_str                                              -      51     +51
static.rtl_p                                           -      42     +42
unicode_conv_to_printable2                           633     477    -156
------------------------------------------------------------------------------
(add/remove: 6/0 grow/shrink: 1/1 up/down: 508/-156)          Total: 352 bytes

Signed-off-by: Tomas Heinrich <heinrich.tomas@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 7c0eef9..be022e8 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -1738,6 +1738,18 @@
 	return ic;
 }
 
+#if ENABLE_UNICODE_BIDI_SUPPORT
+static int isrtl_str(void)
+{
+	int idx = cursor;
+	while (command_ps[idx] >= ' ' && command_ps[idx] < 127 && !isalpha(command_ps[idx]))
+		idx++;
+	return unicode_isrtl(command_ps[idx]);
+}
+#else
+# define isrtl_str() 0
+#endif
+
 /* leave out the "vi-mode"-only case labels if vi editing isn't
  * configured. */
 #define vi_case(caselabel) IF_FEATURE_EDITING_VI(case caselabel)
@@ -1895,10 +1907,9 @@
 			break;
 		case CTRL('B'):
 		vi_case('h'|VI_CMDMODE_BIT:)
-		vi_case('\b'|VI_CMDMODE_BIT:)
+		vi_case('\b'|VI_CMDMODE_BIT:) /* ^H */
 		vi_case('\x7f'|VI_CMDMODE_BIT:) /* DEL */
-			/* Control-b -- Move back one character */
-			input_backward(1);
+			input_backward(1); /* Move back one character */
 			break;
 		case CTRL('E'):
 		vi_case('$'|VI_CMDMODE_BIT:)
@@ -1908,13 +1919,20 @@
 		case CTRL('F'):
 		vi_case('l'|VI_CMDMODE_BIT:)
 		vi_case(' '|VI_CMDMODE_BIT:)
-			/* Control-f -- Move forward one character */
-			input_forward();
+			input_forward(); /* Move forward one character */
 			break;
-		case '\b':
+		case '\b':   /* ^H */
 		case '\x7f': /* DEL */
-			/* Control-h and DEL */
-			input_backspace();
+			if (!isrtl_str())
+				input_backspace();
+			else
+				input_delete(0);
+			break;
+		case KEYCODE_DELETE:
+			if (!isrtl_str())
+				input_delete(0);
+			else
+				input_backspace();
 			break;
 #if ENABLE_FEATURE_TAB_COMPLETION
 		case '\t':
@@ -2137,9 +2155,6 @@
 		case KEYCODE_CTRL_RIGHT:
 			ctrl_right();
 			break;
-		case KEYCODE_DELETE:
-			input_delete(0);
-			break;
 		case KEYCODE_HOME:
 			input_backward(cursor);
 			break;
@@ -2205,14 +2220,19 @@
 				command_ps[cursor] = ic;
 				command_ps[cursor + 1] = BB_NUL;
 				cmdedit_set_out_char(' ');
+				if (unicode_isrtl(ic))
+					input_backward(1);
 			} else {
 				/* In the middle, insert */
+				/* is char right-to-left, or "neutral" one (e.g. comma) added to rtl text? */
+				int rtl = ENABLE_UNICODE_BIDI_SUPPORT ? (unicode_isrtl(ic) || (ic < 127 && !isalpha(ic) && isrtl_str())) : 0;
 				int sc = cursor;
 
 				memmove(command_ps + sc + 1, command_ps + sc,
 					(command_len - sc) * sizeof(command_ps[0]));
 				command_ps[sc] = ic;
-				sc++;
+				if (!rtl)
+					sc++;
 				/* rewrite from cursor */
 				input_end();
 				/* to prev x pos + 1 */