+#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
+static int vi_mode;
+
+void setvimode ( int viflag )
+{
+ vi_mode = viflag;
+}
+
+static void
+vi_Word_motion(char *command, int eat)
+{
+ while (cursor < len && !isspace(command[cursor]))
+ input_forward();
+ if (eat) while (cursor < len && isspace(command[cursor]))
+ input_forward();
+}
+
+static void
+vi_word_motion(char *command, int eat)
+{
+ if (isalnum(command[cursor]) || command[cursor] == '_') {
+ while (cursor < len &&
+ (isalnum(command[cursor+1]) ||
+ command[cursor+1] == '_'))
+ input_forward();
+ } else if (ispunct(command[cursor])) {
+ while (cursor < len &&
+ (ispunct(command[cursor+1])))
+ input_forward();
+ }
+
+ if (cursor < len)
+ input_forward();
+
+ if (eat && cursor < len && isspace(command[cursor]))
+ while (cursor < len && isspace(command[cursor]))
+ input_forward();
+}
+
+static void
+vi_End_motion(char *command)
+{
+ input_forward();
+ while (cursor < len && isspace(command[cursor]))
+ input_forward();
+ while (cursor < len-1 && !isspace(command[cursor+1]))
+ input_forward();
+}
+
+static void
+vi_end_motion(char *command)
+{
+ if (cursor >= len-1)
+ return;
+ input_forward();
+ while (cursor < len-1 && isspace(command[cursor]))
+ input_forward();
+ if (cursor >= len-1)
+ return;
+ if (isalnum(command[cursor]) || command[cursor] == '_') {
+ while (cursor < len-1 &&
+ (isalnum(command[cursor+1]) ||
+ command[cursor+1] == '_'))
+ input_forward();
+ } else if (ispunct(command[cursor])) {
+ while (cursor < len-1 &&
+ (ispunct(command[cursor+1])))
+ input_forward();
+ }
+}
+
+static void
+vi_Back_motion(char *command)
+{
+ while (cursor > 0 && isspace(command[cursor-1]))
+ input_backward(1);
+ while (cursor > 0 && !isspace(command[cursor-1]))
+ input_backward(1);
+}
+
+static void
+vi_back_motion(char *command)
+{
+ if (cursor <= 0)
+ return;
+ input_backward(1);
+ while (cursor > 0 && isspace(command[cursor]))
+ input_backward(1);
+ if (cursor <= 0)
+ return;
+ if (isalnum(command[cursor]) || command[cursor] == '_') {
+ while (cursor > 0 &&
+ (isalnum(command[cursor-1]) ||
+ command[cursor-1] == '_'))
+ input_backward(1);
+ } else if (ispunct(command[cursor])) {
+ while (cursor > 0 &&
+ (ispunct(command[cursor-1])))
+ input_backward(1);
+ }
+}
+#endif
+
+/*
+ * the normal emacs mode and vi's insert mode are the same.
+ * commands entered when in vi command mode ("escape mode") get
+ * an extra bit added to distinguish them. this lets them share
+ * much of the code in the big switch and while loop. i
+ * experimented with an ugly macro to make the case labels for
+ * these cases go away entirely when vi mode isn't configured, in
+ * hopes of letting the jump tables get smaller:
+ * #define vcase(caselabel) caselabel
+ * and then
+ * case CNTRL('A'):
+ * case vcase(VICMD('0'):)
+ * but it didn't seem to make any difference in code size,
+ * and the macro-ized code was too ugly.
+ */
+
+#define VI_cmdbit 0x100
+#define VICMD(somecmd) ((somecmd)|VI_cmdbit)
+
+/* convert uppercase ascii to equivalent control char, for readability */
+#define CNTRL(uc_char) ((uc_char) - 0x40)
+