commit e70ff87c862ffc2d96fcc3c43d15ee8aabc44573
parent db10a421dcc5df2cabd813c6d81ed85d3c8fec52
Author: Benno Schulenberg <bensberg@telfort.nl>
Date: Sun, 26 Jan 2020 16:02:40 +0100
tweaks: move another function to after the one that it calls
(The diff is stupid. It should just remove 440 contiguous lines, and
add back 440 contiguous lines further down. Instead it tries to find
similarities between what is moved and what remains, and makes a mess.
You have to use --patience or --minimal to get the better diff.)
Diffstat:
M | src/proto.h | | | 1 | - |
M | src/winio.c | | | 1872 | ++++++++++++++++++++++++++++++++++++++++---------------------------------------- |
2 files changed, 936 insertions(+), 937 deletions(-)
diff --git a/src/proto.h b/src/proto.h
@@ -615,7 +615,6 @@ size_t get_key_buffer_len(void);
void implant(const char *string);
#endif
int parse_kbinput(WINDOW *win);
-int parse_escape_sequence(WINDOW *win, int kbinput);
int get_kbinput(WINDOW *win, bool showcursor);
int get_byte_kbinput(int kbinput);
int get_control_kbinput(int kbinput);
diff --git a/src/winio.c b/src/winio.c
@@ -321,996 +321,996 @@ int *get_input(WINDOW *win, size_t input_len)
return input;
}
-/* Extract a single keystroke from the input stream. Translate escape
- * sequences and extended keypad codes into their corresponding values.
- * Set meta_key to TRUE when appropriate. Supported extended keypad values
- * are: [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
- * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
- * the function keys (F1-F16), and the numeric keypad with NumLock off. */
-int parse_kbinput(WINDOW *win)
+/* Return the arrow-key code that corresponds to the given letter.
+ * (This mapping is common to a handful of escape sequences.) */
+int arrow_from_ABCD(int letter)
{
- static int escapes = 0;
- static bool double_esc = FALSE;
- int *kbinput, keycode, retval = ERR;
-
- meta_key = FALSE;
- shift_held = FALSE;
-
- /* Read in a character. */
- kbinput = get_input(win, 1);
-
- if (kbinput == NULL && !waiting_mode)
- return ERR;
-
- while (kbinput == NULL)
- kbinput = get_input(win, 1);
-
- keycode = *kbinput;
- free(kbinput);
-
- if (keycode == ERR)
- return ERR;
-
- if (keycode == ESC_CODE) {
- /* Increment the escape counter, but trim an overabundance. */
- escapes++;
- if (escapes > 3)
- escapes = 1;
- /* Take note when an Esc arrived by itself. */
- solitary = (key_buffer_len == 0);
- return ERR;
- }
+ if (letter < 'C')
+ return (letter == 'A' ? KEY_UP : KEY_DOWN);
+ else
+ return (letter == 'D' ? KEY_LEFT : KEY_RIGHT);
+}
- switch (escapes) {
- case 0:
- /* One non-escape: normal input mode. */
- retval = keycode;
- break;
- case 1:
- if (keycode >= 0x80)
- retval = keycode;
- else if (keycode == TAB_CODE)
- retval = SHIFT_TAB;
- else if ((keycode != 'O' && keycode != 'o' && keycode != '[') ||
- key_buffer_len == 0 || *key_buffer == ESC_CODE) {
- /* One escape followed by a single non-escape:
- * meta key sequence mode. */
- if (!solitary || (keycode >= 0x20 && keycode < 0x7F))
- meta_key = TRUE;
- retval = (shifted_metas) ? keycode : tolower(keycode);
- } else
- /* One escape followed by a non-escape, and there
- * are more codes waiting: escape sequence mode. */
- retval = parse_escape_sequence(win, keycode);
- escapes = 0;
- break;
- case 2:
- if (double_esc) {
- /* An "ESC ESC [ X" sequence from Option+arrow, or
- * an "ESC ESC [ x" sequence from Shift+Alt+arrow. */
- switch (keycode) {
- case 'A':
- retval = KEY_HOME;
- break;
- case 'B':
- retval = KEY_END;
- break;
- case 'C':
- retval = CONTROL_RIGHT;
- break;
- case 'D':
- retval = CONTROL_LEFT;
- break;
-#ifndef NANO_TINY
- case 'a':
- retval = shiftaltup;
- break;
- case 'b':
- retval = shiftaltdown;
+/* Translate escape sequences, most of which correspond to extended
+ * keypad values, into their corresponding key values. These sequences
+ * are generated when the keypad doesn't support the needed keys.
+ * Assume that Escape has already been read in. */
+int convert_sequence(const int *seq, size_t length, int *consumed)
+{
+ if (length > 1) {
+ *consumed = 2;
+ switch (seq[0]) {
+ case 'O':
+ switch (seq[1]) {
+ case '1':
+ if (length > 4 && seq[2] == ';') {
+ /* <-<-<-<-<-<-<- */
+ *consumed = 5;
+ switch (seq[3]) {
+ case '2':
+ switch (seq[4]) {
+ case 'A': /* Esc O 1 ; 2 A == Shift-Up on Terminal. */
+ case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */
+ case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */
+ case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */
+ shift_held = TRUE;
+ return arrow_from_ABCD(seq[4]);
+#ifdef ENABLE_NANORC
+ case 'P': /* Esc O 1 ; 2 P == F13 on Gnome Terminal. */
+ case 'Q': /* Esc O 1 ; 2 Q == F14 on Gnome Terminal. */
+ case 'R': /* Esc O 1 ; 2 R == F15 on Gnome Terminal. */
+ case 'S': /* Esc O 1 ; 2 S == F16 on Gnome Terminal. */
+ return KEY_F(13 + seq[4] - 'P');
+#endif
+ }
+ break;
+ case '5':
+ switch (seq[4]) {
+ case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */
+ return CONTROL_UP;
+ case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */
+ return CONTROL_DOWN;
+ case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */
+ return CONTROL_RIGHT;
+ case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */
+ return CONTROL_LEFT;
+ }
+ break;
+ }
+ /* ->->->->->->-> */
+ }
break;
- case 'c':
- retval = shiftaltright;
+ case '2':
+ if (length > 2) {
+ *consumed = 3;
+#ifdef ENABLE_NANORC
+ if ('O' < seq[2] && seq[2] < 'T')
+ /* Esc O 2 P == F13 on Konsole. */
+ /* Esc O 2 Q == F14 on Konsole. */
+ /* Esc O 2 R == F15 on Konsole. */
+ /* Esc O 2 S == F16 on Konsole. */
+ return KEY_F(13 + seq[2] - 'P');
+#endif
+ }
break;
- case 'd':
- retval = shiftaltleft;
+ case '5':
+ if (length > 2) {
+ *consumed = 3;
+ switch (seq[2]) {
+ case 'A': /* Esc O 5 A == Ctrl-Up on Haiku. */
+ return CONTROL_UP;
+ case 'B': /* Esc O 5 B == Ctrl-Down on Haiku. */
+ return CONTROL_DOWN;
+ case 'C': /* Esc O 5 C == Ctrl-Right on Haiku. */
+ return CONTROL_RIGHT;
+ case 'D': /* Esc O 5 D == Ctrl-Left on Haiku. */
+ return CONTROL_LEFT;
+ }
+ }
break;
-#endif
+ case 'A': /* Esc O A == Up on VT100/VT320. */
+ case 'B': /* Esc O B == Down on VT100/VT320. */
+ case 'C': /* Esc O C == Right on VT100/VT320. */
+ case 'D': /* Esc O D == Left on VT100/VT320. */
+ return arrow_from_ABCD(seq[1]);
+ case 'F': /* Esc O F == End on Gnome and Xfce Terminal. */
+ return KEY_END;
+ case 'H': /* Esc O H == Home on Gnome and Xfce Terminal. */
+ return KEY_HOME;
+ case 'M': /* Esc O M == Enter on numeric keypad with
+ * NumLock off on VT100/VT220/VT320/xterm/
+ * rxvt/Eterm. */
+ return KEY_ENTER;
+ case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach console. */
+ case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach console. */
+ case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach console. */
+ case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach console. */
+ case 'T': /* Esc O T == F5 on Mach console. */
+ case 'U': /* Esc O U == F6 on Mach console. */
+ case 'V': /* Esc O V == F7 on Mach console. */
+ case 'W': /* Esc O W == F8 on Mach console. */
+ case 'X': /* Esc O X == F9 on Mach console. */
+ case 'Y': /* Esc O Y == F10 on Mach console. */
+ return KEY_F(seq[1] - 'O');
+ case 'a': /* Esc O a == Ctrl-Up on rxvt/Eterm. */
+ return CONTROL_UP;
+ case 'b': /* Esc O b == Ctrl-Down on rxvt/Eterm. */
+ return CONTROL_DOWN;
+ case 'c': /* Esc O c == Ctrl-Right on rxvt/Eterm. */
+ return CONTROL_RIGHT;
+ case 'd': /* Esc O d == Ctrl-Left on rxvt/Eterm. */
+ return CONTROL_LEFT;
+ case 'j': /* Esc O j == '*' on numeric keypad with
+ * NumLock off on VT100/VT220/VT320/xterm/
+ * rxvt/Eterm/Terminal. */
+ return '*';
+ case 'k': /* Esc O k == '+' on the same. */
+ return '+';
+ case 'l': /* Esc O l == ',' on the same. */
+ return ',';
+ case 'm': /* Esc O m == '-' on the same. */
+ return '-';
+ case 'n': /* Esc O n == Delete (.) on the same. */
+ return KEY_DC;
+ case 'o': /* Esc O o == '/' on the same. */
+ return '/';
+ case 'p': /* Esc O p == Insert (0) on numeric keypad
+ * with NumLock off on VT100/VT220/VT320/
+ * rxvt/Eterm/Terminal. */
+ return KEY_IC;
+ case 'q': /* Esc O q == End (1) on the same. */
+ return KEY_END;
+ case 'r': /* Esc O r == Down (2) on the same. */
+ return KEY_DOWN;
+ case 's': /* Esc O s == PageDown (3) on the same. */
+ return KEY_NPAGE;
+ case 't': /* Esc O t == Left (4) on the same. */
+ return KEY_LEFT;
+ case 'v': /* Esc O v == Right (6) on numeric keypad
+ * with NumLock off on VT100/VT220/VT320/
+ * rxvt/Eterm/Terminal. */
+ return KEY_RIGHT;
+ case 'w': /* Esc O w == Home (7) on the same. */
+ return KEY_HOME;
+ case 'x': /* Esc O x == Up (8) on the same. */
+ return KEY_UP;
+ case 'y': /* Esc O y == PageUp (9) on the same. */
+ return KEY_PPAGE;
}
- double_esc = FALSE;
- escapes = 0;
- } else if (key_buffer_len == 0) {
- if ('0' <= keycode && ((keycode <= '2' && digit_count == 0) ||
- (keycode <= '9' && digit_count > 0))) {
- /* Two escapes followed by one or more decimal
- * digits, and there aren't any other codes
- * waiting: byte sequence mode. If the range of the
- * byte sequence is limited to 2XX, interpret it. */
- int byte = get_byte_kbinput(keycode);
-
- /* If the decimal byte value is complete, convert it and
- * put the obtained byte(s) back into the input buffer. */
- if (byte != ERR) {
- char *multibyte;
- int count, onebyte, i;
-
- /* Convert the decimal code to one or two bytes. */
- multibyte = make_mbchar((long)byte, &count);
-
- /* Insert the byte(s) into the input buffer. */
- for (i = count; i > 0 ; i--) {
- onebyte = (unsigned char)multibyte[i - 1];
- put_back(onebyte);
- }
-
- free(multibyte);
-
- escapes = 0;
- }
- } else {
- if (digit_count == 0)
- /* Two escapes followed by a non-digit: meta key
- * or control character sequence mode. */
- if (!solitary) {
- meta_key = TRUE;
- retval = (shifted_metas) ? keycode : tolower(keycode);
- } else
- retval = get_control_kbinput(keycode);
- else {
- /* An invalid digit in the middle of a byte
- * sequence: reset the byte sequence counter
- * and save the code we got as the result. */
- digit_count = 0;
- retval = keycode;
- }
- escapes = 0;
+ break;
+ case '[':
+ if (seq[1] < '9')
+ *consumed = 3;
+ switch (seq[1]) {
+ case '1':
+ if (length > 2 && seq[2] == '~')
+ /* Esc [ 1 ~ == Home on VT320/Linux console. */
+ return KEY_HOME;
+ else if (length > 3 && seq[3] == '~') {
+ *consumed = 4;
+ switch (seq[2]) {
+ case '1': /* Esc [ 1 1 ~ == F1 on rxvt/Eterm. */
+ case '2': /* Esc [ 1 2 ~ == F2 on rxvt/Eterm. */
+ case '3': /* Esc [ 1 3 ~ == F3 on rxvt/Eterm. */
+ case '4': /* Esc [ 1 4 ~ == F4 on rxvt/Eterm. */
+ case '5': /* Esc [ 1 5 ~ == F5 on xterm/rxvt/Eterm. */
+ return KEY_F(seq[2] - '0');
+ case '7': /* Esc [ 1 7 ~ == F6 on VT220/VT320/
+ * Linux console/xterm/rxvt/Eterm. */
+ case '8': /* Esc [ 1 8 ~ == F7 on the same. */
+ case '9': /* Esc [ 1 9 ~ == F8 on the same. */
+ return KEY_F(seq[2] - '1');
+ }
+ } else if (length > 4 && seq[2] == ';') {
+ /* <-<-<-<-<-<-<- */
+ *consumed = 5;
+ switch (seq[3]) {
+ case '2':
+ switch (seq[4]) {
+ case 'A': /* Esc [ 1 ; 2 A == Shift-Up on xterm. */
+ case 'B': /* Esc [ 1 ; 2 B == Shift-Down on xterm. */
+ case 'C': /* Esc [ 1 ; 2 C == Shift-Right on xterm. */
+ case 'D': /* Esc [ 1 ; 2 D == Shift-Left on xterm. */
+ shift_held = TRUE;
+ return arrow_from_ABCD(seq[4]);
+#ifndef NANO_TINY
+ case 'F': /* Esc [ 1 ; 2 F == Shift-End on xterm. */
+ return SHIFT_END;
+ case 'H': /* Esc [ 1 ; 2 H == Shift-Home on xterm. */
+ return SHIFT_HOME;
+#endif
+#ifdef ENABLE_NANORC
+ case 'P': /* Esc [ 1 ; 2 P == F13 on xterm. */
+ case 'Q': /* Esc [ 1 ; 2 Q == F14 on xterm. */
+ case 'R': /* Esc [ 1 ; 2 R == F15 on xterm. */
+ case 'S': /* Esc [ 1 ; 2 S == F16 on xterm. */
+ return KEY_F(13 + seq[4] - 'P');
+#endif
}
- } else if (keycode == '[' && key_buffer_len > 0 &&
- (('A' <= *key_buffer && *key_buffer <= 'D') ||
- ('a' <= *key_buffer && *key_buffer <= 'd'))) {
- /* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */
- double_esc = TRUE;
- } else {
- /* Two escapes followed by a non-escape, and there are more
- * codes waiting: combined meta and escape sequence mode. */
- retval = parse_escape_sequence(win, keycode);
- meta_key = TRUE;
- escapes = 0;
- }
- break;
- case 3:
- if (key_buffer_len == 0) {
- if (!solitary) {
- meta_key = TRUE;
- retval = (shifted_metas) ? keycode : tolower(keycode);
- } else
- /* Three escapes followed by a non-escape, and no
- * other codes are waiting: normal input mode. */
- retval = keycode;
- } else
- /* Three escapes followed by a non-escape, and more
- * codes are waiting: combined control character and
- * escape sequence mode. First interpret the escape
- * sequence, then the result as a control sequence. */
- retval = get_control_kbinput(
- parse_escape_sequence(win, keycode));
- escapes = 0;
- break;
- }
-
- if (retval == ERR)
- return ERR;
-
- if (retval == controlleft)
- return CONTROL_LEFT;
- else if (retval == controlright)
- return CONTROL_RIGHT;
- else if (retval == controlup)
- return CONTROL_UP;
- else if (retval == controldown)
- return CONTROL_DOWN;
- else if (retval == controlhome)
- return CONTROL_HOME;
- else if (retval == controlend)
- return CONTROL_END;
+ break;
#ifndef NANO_TINY
- else if (retval == controldelete)
- return CONTROL_DELETE;
- else if (retval == controlshiftdelete)
- return CONTROL_SHIFT_DELETE;
- else if (retval == shiftup) {
- shift_held = TRUE;
- return KEY_UP;
- } else if (retval == shiftdown) {
- shift_held = TRUE;
- return KEY_DOWN;
- } else if (retval == shiftcontrolleft) {
- shift_held = TRUE;
- return CONTROL_LEFT;
- } else if (retval == shiftcontrolright) {
- shift_held = TRUE;
- return CONTROL_RIGHT;
- } else if (retval == shiftcontrolup) {
- shift_held = TRUE;
- return CONTROL_UP;
- } else if (retval == shiftcontroldown) {
- shift_held = TRUE;
- return CONTROL_DOWN;
- } else if (retval == shiftcontrolhome) {
- shift_held = TRUE;
- return CONTROL_HOME;
- } else if (retval == shiftcontrolend) {
- shift_held = TRUE;
- return CONTROL_END;
- } else if (retval == altleft)
- return ALT_LEFT;
- else if (retval == altright)
- return ALT_RIGHT;
- else if (retval == altup)
- return ALT_UP;
- else if (retval == altdown)
- return ALT_DOWN;
- else if (retval == altdelete)
- return ALT_DELETE;
- else if (retval == shiftaltleft) {
- shift_held = TRUE;
- return KEY_HOME;
- } else if (retval == shiftaltright) {
- shift_held = TRUE;
- return KEY_END;
- } else if (retval == shiftaltup) {
- shift_held = TRUE;
- return KEY_PPAGE;
- } else if (retval == shiftaltdown) {
- shift_held = TRUE;
- return KEY_NPAGE;
- }
+ case '9': /* To accommodate iTerm2 in "xterm mode". */
+ case '3':
+ switch (seq[4]) {
+ case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */
+ return ALT_UP;
+ case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */
+ return ALT_DOWN;
+ case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */
+ return ALT_RIGHT;
+ case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */
+ return ALT_LEFT;
+ }
+ break;
+ case '4':
+ /* When the arrow keys are held together with Shift+Meta,
+ * act as if they are Home/End/PgUp/PgDown with Shift. */
+ switch (seq[4]) {
+ case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */
+ return SHIFT_PAGEUP;
+ case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */
+ return SHIFT_PAGEDOWN;
+ case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */
+ return SHIFT_END;
+ case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */
+ return SHIFT_HOME;
+ }
+ break;
#endif
-
-#ifdef __linux__
- /* When not running under X, check for the bare arrow keys whether
- * Shift/Ctrl/Alt are being held together with them. */
- unsigned char modifiers = 6;
-
- /* Modifiers are: Alt (8), Ctrl (4), Shift (1). */
- if (on_a_vt && !mute_modifiers && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
+ case '5':
+ switch (seq[4]) {
+ case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
+ return CONTROL_UP;
+ case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */
+ return CONTROL_DOWN;
+ case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */
+ return CONTROL_RIGHT;
+ case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */
+ return CONTROL_LEFT;
+ case 'F': /* Esc [ 1 ; 5 F == Ctrl-End on xterm. */
+ return CONTROL_END;
+ case 'H': /* Esc [ 1 ; 5 H == Ctrl-Home on xterm. */
+ return CONTROL_HOME;
+ }
+ break;
#ifndef NANO_TINY
- /* Is Delete pressed together with Shift or Shift+Ctrl? */
- if (retval == KEY_DC) {
- if (modifiers == 0x01)
- return SHIFT_DELETE;
- if (modifiers == 0x05)
- return CONTROL_SHIFT_DELETE;
+ case '6':
+ switch (seq[4]) {
+ case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */
+ return shiftcontrolup;
+ case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */
+ return shiftcontroldown;
+ case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */
+ return shiftcontrolright;
+ case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */
+ return shiftcontrolleft;
+ case 'F': /* Esc [ 1 ; 6 F == Shift-Ctrl-End on xterm. */
+ return shiftcontrolend;
+ case 'H': /* Esc [ 1 ; 6 H == Shift-Ctrl-Home on xterm. */
+ return shiftcontrolhome;
+ }
+ break;
+#endif
}
- /* Is Shift being held? */
- if (modifiers & 0x01) {
- if (retval == TAB_CODE)
- return SHIFT_TAB;
- if (!meta_key)
- shift_held = TRUE;
- }
- /* Is Alt being held? */
- if (modifiers == 0x08) {
- if (retval == KEY_DC)
- return ALT_DELETE;
- if (retval == KEY_UP)
- return ALT_UP;
- if (retval == KEY_DOWN)
- return ALT_DOWN;
- }
-#endif
- /* Is Ctrl being held? */
- if (modifiers & 0x04) {
- if (retval == KEY_UP)
- return CONTROL_UP;
- else if (retval == KEY_DOWN)
- return CONTROL_DOWN;
- else if (retval == KEY_LEFT)
- return CONTROL_LEFT;
- else if (retval == KEY_RIGHT)
- return CONTROL_RIGHT;
- else if (retval == KEY_HOME)
- return CONTROL_HOME;
- else if (retval == KEY_END)
- return CONTROL_END;
- else if (retval == KEY_DC)
- return CONTROL_DELETE;
- }
-#ifndef NANO_TINY
- /* Are both Shift and Alt being held? */
- if ((modifiers & 0x09) == 0x09) {
- if (retval == KEY_UP)
- return KEY_PPAGE;
- else if (retval == KEY_DOWN)
- return KEY_NPAGE;
- else if (retval == KEY_LEFT)
- return KEY_HOME;
- else if (retval == KEY_RIGHT)
- return KEY_END;
- }
-#endif
- }
-#endif /* __linux__ */
-
-#ifndef NANO_TINY
- /* When <Tab> is pressed while the mark is on, do an indent. */
- if (retval == TAB_CODE && openfile->mark && currmenu == MMAIN &&
- !bracketed_paste && openfile->mark != openfile->current)
- return INDENT_KEY;
-#endif
-
- switch (retval) {
-#ifdef KEY_SLEFT /* Slang doesn't support KEY_SLEFT. */
- case KEY_SLEFT:
- shift_held = TRUE;
- return KEY_LEFT;
-#endif
-#ifdef KEY_SRIGHT /* Slang doesn't support KEY_SRIGHT. */
- case KEY_SRIGHT:
- shift_held = TRUE;
- return KEY_RIGHT;
-#endif
-#ifdef KEY_SR
-#ifdef KEY_SUP /* ncurses and Slang don't support KEY_SUP. */
- case KEY_SUP:
-#endif
- case KEY_SR: /* Scroll backward, on Xfce4-terminal. */
- shift_held = TRUE;
- return KEY_UP;
+ /* ->->->->->->-> */
+ } else if (length > 5 && seq[3] == ';' && seq[5] == '~')
+ /* Esc [ 1 n ; 2 ~ == F17...F20 on some terminals. */
+ *consumed = 6;
+#ifdef USE_SLANG
+ else if (length == 4 && seq[3] == ';')
+ /* Discard broken sequences that Slang produces. */
+ *consumed = 4;
#endif
-#ifdef KEY_SF
-#ifdef KEY_SDOWN /* ncurses and Slang don't support KEY_SDOWN. */
- case KEY_SDOWN:
+ break;
+ case '2':
+ if (length > 3 && seq[3] == '~') {
+ *consumed = 4;
+ switch (seq[2]) {
+ case '0': /* Esc [ 2 0 ~ == F9 on VT220/VT320/
+ * Linux console/xterm/rxvt/Eterm. */
+ return KEY_F(9);
+ case '1': /* Esc [ 2 1 ~ == F10 on the same. */
+ return KEY_F(10);
+ case '3': /* Esc [ 2 3 ~ == F11 on the same. */
+ return KEY_F(11);
+ case '4': /* Esc [ 2 4 ~ == F12 on the same. */
+ return KEY_F(12);
+#ifdef ENABLE_NANORC
+ case '5': /* Esc [ 2 5 ~ == F13 on VT220/VT320/
+ * Linux console/rxvt/Eterm. */
+ return KEY_F(13);
+ case '6': /* Esc [ 2 6 ~ == F14 on the same. */
+ return KEY_F(14);
+ case '8': /* Esc [ 2 8 ~ == F15 on the same. */
+ return KEY_F(15);
+ case '9': /* Esc [ 2 9 ~ == F16 on the same. */
+ return KEY_F(16);
#endif
- case KEY_SF: /* Scroll forward, on Xfce4-terminal. */
- shift_held = TRUE;
- return KEY_DOWN;
+ }
+ } else if (length > 2 && seq[2] == '~')
+ /* Esc [ 2 ~ == Insert on VT220/VT320/
+ * Linux console/xterm/Terminal. */
+ return KEY_IC;
+ else if (length > 4 && seq[2] == ';' && seq[4] == '~')
+ /* Esc [ 2 ; x ~ == modified Insert on xterm. */
+ *consumed = 5;
+ else if (length > 5 && seq[3] == ';' && seq[5] == '~')
+ /* Esc [ 2 n ; 2 ~ == F21...F24 on some terminals. */
+ *consumed = 6;
+#ifdef USE_SLANG
+ else if (length == 4 && seq[3] == ';')
+ /* Discard broken sequences that Slang produces. */
+ *consumed = 4;
#endif
-#ifdef KEY_SHOME /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
- case KEY_SHOME:
+#ifndef NANO_TINY
+ else if (length > 4 && seq[2] == '0' && seq[4] == '~') {
+ /* Esc [ 2 0 0 ~ == start of a bracketed paste,
+ * Esc [ 2 0 1 ~ == end of a bracketed paste. */
+ *consumed = 5;
+ if (seq[3] == '0') {
+ bracketed_paste = TRUE;
+ return BRACKETED_PASTE_MARKER;
+ } else if (seq[3] == '1') {
+ bracketed_paste = FALSE;
+ return BRACKETED_PASTE_MARKER;
+ }
+ }
#endif
- case SHIFT_HOME:
- shift_held = TRUE;
- case KEY_A1: /* Home (7) on keypad with NumLock off. */
- return KEY_HOME;
-#ifdef KEY_SEND /* HP-UX 10-11 and Slang don't support KEY_SEND. */
- case KEY_SEND:
+ break;
+ case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
+ * Linux console/xterm/Terminal. */
+ if (length > 2 && seq[2] == '~')
+ return KEY_DC;
+ if (length > 4 && seq[2] == ';' && seq[4] == '~') {
+ *consumed = 5;
+#ifndef NANO_TINY
+ if (seq[3] == '2')
+ /* Esc [ 3 ; 2 ~ == Shift-Delete on xterm/Terminal. */
+ return SHIFT_DELETE;
+ if (seq[3] == '3')
+ /* Esc [ 3 ; 3 ~ == Alt-Delete on xterm/rxvt/Eterm/Terminal. */
+ return ALT_DELETE;
+ if (seq[3] == '5')
+ /* Esc [ 3 ; 5 ~ == Ctrl-Delete on xterm. */
+ return CONTROL_DELETE;
+ if (seq[3] == '6')
+ /* Esc [ 3 ; 6 ~ == Ctrl-Shift-Delete on xterm. */
+ return controlshiftdelete;
#endif
- case SHIFT_END:
- shift_held = TRUE;
- case KEY_C1: /* End (1) on keypad with NumLock off. */
- return KEY_END;
-#ifdef KEY_EOL
- case KEY_EOL: /* Ctrl+End on rxvt-unicode. */
- return CONTROL_END;
+ }
+#ifndef NANO_TINY
+ if (length > 2 && seq[2] == '$')
+ /* Esc [ 3 $ == Shift-Delete on urxvt. */
+ return SHIFT_DELETE;
+ if (length > 2 && seq[2] == '^')
+ /* Esc [ 3 ^ == Ctrl-Delete on urxvt. */
+ return CONTROL_DELETE;
+ if (length > 2 && seq[2] == '@')
+ /* Esc [ 3 @ == Ctrl-Shift-Delete on urxvt. */
+ return controlshiftdelete;
+ if (length > 3 && seq[3] == '~')
+ /* Esc [ 3 n ~ == F17...F20 on some terminals. */
+ *consumed = 4;
#endif
+ break;
+ case '4': /* Esc [ 4 ~ == End on VT220/VT320/
+ * Linux console/xterm. */
+ if (length > 2 && seq[2] == '~')
+ return KEY_END;
+ break;
+ case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
+ * Linux console/xterm/Eterm/urxvt/Terminal */
+ if (length > 2 && seq[2] == '~')
+ return KEY_PPAGE;
+ else if (length > 4 && seq[2] == ';' && seq[4] == '~') {
+ *consumed = 5;
#ifndef NANO_TINY
-#ifdef KEY_SPREVIOUS
- case KEY_SPREVIOUS:
+ if (seq[3] == '2')
+ return shiftaltup;
#endif
- case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */
- shift_held = TRUE;
+ }
+ break;
+ case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
+ * Linux console/xterm/Eterm/urxvt/Terminal */
+ if (length > 2 && seq[2] == '~')
+ return KEY_NPAGE;
+ else if (length > 4 && seq[2] == ';' && seq[4] == '~') {
+ *consumed = 5;
+#ifndef NANO_TINY
+ if (seq[3] == '2')
+ return shiftaltdown;
#endif
- case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
- return KEY_PPAGE;
+ }
+ break;
+ case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt;
+ * Esc [ 7 $ == Shift-Home on Eterm/rxvt;
+ * Esc [ 7 ^ == Control-Home on Eterm/rxvt;
+ * Esc [ 7 @ == Shift-Control-Home on same. */
+ if (length > 2 && seq[2] == '~')
+ return KEY_HOME;
+ else if (length > 2 && seq[2] == '$')
+ return SHIFT_HOME;
+ else if (length > 2 && seq[2] == '^')
+ return CONTROL_HOME;
#ifndef NANO_TINY
-#ifdef KEY_SNEXT
- case KEY_SNEXT:
+ else if (length > 2 && seq[2] == '@')
+ return shiftcontrolhome;
#endif
- case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */
- shift_held = TRUE;
+ break;
+ case '8': /* Esc [ 8 ~ == End on Eterm/rxvt;
+ * Esc [ 8 $ == Shift-End on Eterm/rxvt;
+ * Esc [ 8 ^ == Control-End on Eterm/rxvt;
+ * Esc [ 8 @ == Shift-Control-End on same. */
+ if (length > 2 && seq[2] == '~')
+ return KEY_END;
+ else if (length > 2 && seq[2] == '$')
+ return SHIFT_END;
+ else if (length > 2 && seq[2] == '^')
+ return CONTROL_END;
+#ifndef NANO_TINY
+ else if (length > 2 && seq[2] == '@')
+ return shiftcontrolend;
#endif
- case KEY_C3: /* PageDown (3) on keypad with NumLock off. */
- return KEY_NPAGE;
- /* When requested, swap meanings of keycodes for <Bsp> and <Del>. */
- case DEL_CODE:
- case KEY_BACKSPACE:
- return (ISSET(REBIND_DELETE) ? KEY_DC : KEY_BACKSPACE);
- case KEY_DC:
- return (ISSET(REBIND_DELETE) ? KEY_BACKSPACE : KEY_DC);
-#ifdef KEY_SDC /* Slang doesn't support KEY_SDC. */
- case KEY_SDC:
- return SHIFT_DELETE;
-#endif
-#ifdef KEY_SIC /* Slang doesn't support KEY_SIC. */
- case KEY_SIC:
- return the_code_for(do_insertfile_void, KEY_IC);
-#endif
-#ifdef KEY_CANCEL /* Slang doesn't support KEY_CANCEL. */
-#ifdef KEY_SCANCEL /* Slang doesn't support KEY_SCANCEL. */
- case KEY_SCANCEL:
-#endif
- case KEY_CANCEL:
- return the_code_for(do_cancel, 0x03);
-#endif
-#ifdef KEY_SUSPEND /* Slang doesn't support KEY_SUSPEND. */
-#ifdef KEY_SSUSPEND /* Slang doesn't support KEY_SSUSPEND. */
- case KEY_SSUSPEND:
-#endif
- case KEY_SUSPEND:
- return the_code_for(do_suspend_void, KEY_SUSPEND);
-#endif
-#ifdef KEY_BTAB /* Slang doesn't support KEY_BTAB. */
- case KEY_BTAB:
- return SHIFT_TAB;
-#endif
-#ifdef KEY_SBEG /* Slang doesn't support KEY_SBEG. */
- case KEY_SBEG:
-#endif
-#ifdef KEY_BEG /* Slang doesn't support KEY_BEG. */
- case KEY_BEG:
-#endif
- case KEY_B2: /* Center (5) on keypad with NumLock off. */
-#ifdef PDCURSES
- case KEY_SHIFT_L:
- case KEY_SHIFT_R:
- case KEY_CONTROL_L:
- case KEY_CONTROL_R:
- case KEY_ALT_L:
- case KEY_ALT_R:
-#endif
-#ifdef KEY_RESIZE /* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
- case KEY_RESIZE:
-#endif
-#if defined(USE_SLANG) && defined(ENABLE_UTF8)
- case KEY_BAD:
-#endif
- case KEY_FLUSH:
- return ERR; /* Ignore this keystroke. */
- }
-
- return retval;
-}
-
-/* Return the arrow-key code that corresponds to the given letter.
- * (This mapping is common to a handful of escape sequences.) */
-int arrow_from_ABCD(int letter)
-{
- if (letter < 'C')
- return (letter == 'A' ? KEY_UP : KEY_DOWN);
- else
- return (letter == 'D' ? KEY_LEFT : KEY_RIGHT);
-}
-
-/* Translate escape sequences, most of which correspond to extended
- * keypad values, into their corresponding key values. These sequences
- * are generated when the keypad doesn't support the needed keys.
- * Assume that Escape has already been read in. */
-int convert_sequence(const int *seq, size_t length, int *consumed)
-{
- if (length > 1) {
- *consumed = 2;
- switch (seq[0]) {
- case 'O':
- switch (seq[1]) {
- case '1':
- if (length > 4 && seq[2] == ';') {
- /* <-<-<-<-<-<-<- */
- *consumed = 5;
- switch (seq[3]) {
- case '2':
- switch (seq[4]) {
- case 'A': /* Esc O 1 ; 2 A == Shift-Up on Terminal. */
- case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */
- case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */
- case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */
- shift_held = TRUE;
- return arrow_from_ABCD(seq[4]);
-#ifdef ENABLE_NANORC
- case 'P': /* Esc O 1 ; 2 P == F13 on Gnome Terminal. */
- case 'Q': /* Esc O 1 ; 2 Q == F14 on Gnome Terminal. */
- case 'R': /* Esc O 1 ; 2 R == F15 on Gnome Terminal. */
- case 'S': /* Esc O 1 ; 2 S == F16 on Gnome Terminal. */
- return KEY_F(13 + seq[4] - 'P');
-#endif
- }
- break;
- case '5':
- switch (seq[4]) {
- case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */
- return CONTROL_UP;
- case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */
- return CONTROL_DOWN;
- case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */
- return CONTROL_RIGHT;
- case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */
- return CONTROL_LEFT;
- }
- break;
- }
- /* ->->->->->->-> */
- }
break;
- case '2':
+ case '9': /* Esc [ 9 == Delete on Mach console. */
+ return KEY_DC;
+ case '@': /* Esc [ @ == Insert on Mach console. */
+ return KEY_IC;
+ case 'A': /* Esc [ A == Up on ANSI/VT220/Linux console/
+ * FreeBSD console/Mach console/xterm/Eterm/
+ * urxvt/Gnome and Xfce Terminal. */
+ case 'B': /* Esc [ B == Down on the same. */
+ case 'C': /* Esc [ C == Right on the same. */
+ case 'D': /* Esc [ D == Left on the same. */
+ return arrow_from_ABCD(seq[1]);
+ case 'F': /* Esc [ F == End on FreeBSD console/Eterm. */
+ return KEY_END;
+ case 'G': /* Esc [ G == PageDown on FreeBSD console. */
+ return KEY_NPAGE;
+ case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
+ * console/Mach console/Eterm. */
+ return KEY_HOME;
+ case 'I': /* Esc [ I == PageUp on FreeBSD console. */
+ return KEY_PPAGE;
+ case 'L': /* Esc [ L == Insert on ANSI/FreeBSD console. */
+ return KEY_IC;
+ case 'M': /* Esc [ M == F1 on FreeBSD console. */
+ return KEY_F(1);
+ case 'N': /* Esc [ N == F2 on FreeBSD console. */
+ return KEY_F(2);
+ case 'O':
if (length > 2) {
*consumed = 3;
-#ifdef ENABLE_NANORC
if ('O' < seq[2] && seq[2] < 'T')
- /* Esc O 2 P == F13 on Konsole. */
- /* Esc O 2 Q == F14 on Konsole. */
- /* Esc O 2 R == F15 on Konsole. */
- /* Esc O 2 S == F16 on Konsole. */
- return KEY_F(13 + seq[2] - 'P');
-#endif
- }
+ /* Esc [ O P == F1 on xterm. */
+ /* Esc [ O Q == F2 on xterm. */
+ /* Esc [ O R == F3 on xterm. */
+ /* Esc [ O S == F4 on xterm. */
+ return KEY_F(seq[2] - 'O');
+ } else
+ /* Esc [ O == F3 on FreeBSD console. */
+ return KEY_F(3);
break;
- case '5':
+ case 'P': /* Esc [ P == F4 on FreeBSD console. */
+ case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
+ case 'R': /* Esc [ R == F6 on FreeBSD console. */
+ case 'S': /* Esc [ S == F7 on FreeBSD console. */
+ case 'T': /* Esc [ T == F8 on FreeBSD console. */
+ return KEY_F(4 + seq[1] - 'P');
+ case 'U': /* Esc [ U == PageDown on Mach console. */
+ return KEY_NPAGE;
+ case 'V': /* Esc [ V == PageUp on Mach console. */
+ return KEY_PPAGE;
+ case 'W': /* Esc [ W == F11 on FreeBSD console. */
+ return KEY_F(11);
+ case 'X': /* Esc [ X == F12 on FreeBSD console. */
+ return KEY_F(12);
+ case 'Y': /* Esc [ Y == End on Mach console. */
+ return KEY_END;
+ case 'Z': /* Esc [ Z == Shift-Tab on ANSI/Linux console/
+ * FreeBSD console/xterm/rxvt/Terminal. */
+ return SHIFT_TAB;
+ case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
+ case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
+ case 'c': /* Esc [ c == Shift-Right on rxvt/Eterm. */
+ case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
+ shift_held = TRUE;
+ return arrow_from_ABCD(toupper(seq[1]));
+ case '[':
if (length > 2) {
*consumed = 3;
- switch (seq[2]) {
- case 'A': /* Esc O 5 A == Ctrl-Up on Haiku. */
- return CONTROL_UP;
- case 'B': /* Esc O 5 B == Ctrl-Down on Haiku. */
- return CONTROL_DOWN;
- case 'C': /* Esc O 5 C == Ctrl-Right on Haiku. */
- return CONTROL_RIGHT;
- case 'D': /* Esc O 5 D == Ctrl-Left on Haiku. */
- return CONTROL_LEFT;
- }
+ if ('@' < seq[2] && seq[2] < 'F')
+ /* Esc [ [ A == F1 on Linux console. */
+ /* Esc [ [ B == F2 on Linux console. */
+ /* Esc [ [ C == F3 on Linux console. */
+ /* Esc [ [ D == F4 on Linux console. */
+ /* Esc [ [ E == F5 on Linux console. */
+ return KEY_F(seq[2] - '@');
}
break;
- case 'A': /* Esc O A == Up on VT100/VT320. */
- case 'B': /* Esc O B == Down on VT100/VT320. */
- case 'C': /* Esc O C == Right on VT100/VT320. */
- case 'D': /* Esc O D == Left on VT100/VT320. */
- return arrow_from_ABCD(seq[1]);
- case 'F': /* Esc O F == End on Gnome and Xfce Terminal. */
- return KEY_END;
- case 'H': /* Esc O H == Home on Gnome and Xfce Terminal. */
- return KEY_HOME;
- case 'M': /* Esc O M == Enter on numeric keypad with
- * NumLock off on VT100/VT220/VT320/xterm/
- * rxvt/Eterm. */
- return KEY_ENTER;
- case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach console. */
- case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach console. */
- case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach console. */
- case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach console. */
- case 'T': /* Esc O T == F5 on Mach console. */
- case 'U': /* Esc O U == F6 on Mach console. */
- case 'V': /* Esc O V == F7 on Mach console. */
- case 'W': /* Esc O W == F8 on Mach console. */
- case 'X': /* Esc O X == F9 on Mach console. */
- case 'Y': /* Esc O Y == F10 on Mach console. */
- return KEY_F(seq[1] - 'O');
- case 'a': /* Esc O a == Ctrl-Up on rxvt/Eterm. */
- return CONTROL_UP;
- case 'b': /* Esc O b == Ctrl-Down on rxvt/Eterm. */
- return CONTROL_DOWN;
- case 'c': /* Esc O c == Ctrl-Right on rxvt/Eterm. */
- return CONTROL_RIGHT;
- case 'd': /* Esc O d == Ctrl-Left on rxvt/Eterm. */
- return CONTROL_LEFT;
- case 'j': /* Esc O j == '*' on numeric keypad with
- * NumLock off on VT100/VT220/VT320/xterm/
- * rxvt/Eterm/Terminal. */
- return '*';
- case 'k': /* Esc O k == '+' on the same. */
- return '+';
- case 'l': /* Esc O l == ',' on the same. */
- return ',';
- case 'm': /* Esc O m == '-' on the same. */
- return '-';
- case 'n': /* Esc O n == Delete (.) on the same. */
- return KEY_DC;
- case 'o': /* Esc O o == '/' on the same. */
- return '/';
- case 'p': /* Esc O p == Insert (0) on numeric keypad
- * with NumLock off on VT100/VT220/VT320/
- * rxvt/Eterm/Terminal. */
- return KEY_IC;
- case 'q': /* Esc O q == End (1) on the same. */
- return KEY_END;
- case 'r': /* Esc O r == Down (2) on the same. */
- return KEY_DOWN;
- case 's': /* Esc O s == PageDown (3) on the same. */
- return KEY_NPAGE;
- case 't': /* Esc O t == Left (4) on the same. */
- return KEY_LEFT;
- case 'v': /* Esc O v == Right (6) on numeric keypad
- * with NumLock off on VT100/VT220/VT320/
- * rxvt/Eterm/Terminal. */
- return KEY_RIGHT;
- case 'w': /* Esc O w == Home (7) on the same. */
- return KEY_HOME;
- case 'x': /* Esc O x == Up (8) on the same. */
- return KEY_UP;
- case 'y': /* Esc O y == PageUp (9) on the same. */
- return KEY_PPAGE;
}
break;
- case '[':
- if (seq[1] < '9')
- *consumed = 3;
- switch (seq[1]) {
- case '1':
- if (length > 2 && seq[2] == '~')
- /* Esc [ 1 ~ == Home on VT320/Linux console. */
- return KEY_HOME;
- else if (length > 3 && seq[3] == '~') {
- *consumed = 4;
- switch (seq[2]) {
- case '1': /* Esc [ 1 1 ~ == F1 on rxvt/Eterm. */
- case '2': /* Esc [ 1 2 ~ == F2 on rxvt/Eterm. */
- case '3': /* Esc [ 1 3 ~ == F3 on rxvt/Eterm. */
- case '4': /* Esc [ 1 4 ~ == F4 on rxvt/Eterm. */
- case '5': /* Esc [ 1 5 ~ == F5 on xterm/rxvt/Eterm. */
- return KEY_F(seq[2] - '0');
- case '7': /* Esc [ 1 7 ~ == F6 on VT220/VT320/
- * Linux console/xterm/rxvt/Eterm. */
- case '8': /* Esc [ 1 8 ~ == F7 on the same. */
- case '9': /* Esc [ 1 9 ~ == F8 on the same. */
- return KEY_F(seq[2] - '1');
- }
- } else if (length > 4 && seq[2] == ';') {
- /* <-<-<-<-<-<-<- */
- *consumed = 5;
- switch (seq[3]) {
- case '2':
- switch (seq[4]) {
- case 'A': /* Esc [ 1 ; 2 A == Shift-Up on xterm. */
- case 'B': /* Esc [ 1 ; 2 B == Shift-Down on xterm. */
- case 'C': /* Esc [ 1 ; 2 C == Shift-Right on xterm. */
- case 'D': /* Esc [ 1 ; 2 D == Shift-Left on xterm. */
- shift_held = TRUE;
- return arrow_from_ABCD(seq[4]);
+ }
+ }
+
+ return ERR;
+}
+
+/* Interpret the escape sequence in the keystroke buffer, the first
+ * character of which is kbinput. Assume that the keystroke buffer
+ * isn't empty, and that the initial escape has already been read in. */
+int parse_escape_sequence(WINDOW *win, int kbinput)
+{
+ int retval, *sequence, length, consumed;
+
+ /* Put back the non-escape code, then grab at most six integers
+ * (the longest possible escape sequence) from the keybuffer and
+ * translate the sequence into its corresponding keycode. */
+ put_back(kbinput);
+ length = (key_buffer_len < 6 ? key_buffer_len : 6);
+ sequence = get_input(NULL, length);
+ retval = convert_sequence(sequence, length, &consumed);
+
+ /* If not all grabbed integers were consumed, put the leftovers back. */
+ for (int i = length - 1; i >= consumed; i--)
+ put_back(sequence[i]);
+
+ free(sequence);
+
+ /* If we got an unrecognized escape sequence, notify the user. */
+ if (retval == ERR && win == edit) {
+ /* TRANSLATORS: This refers to a sequence of escape codes
+ * (from the keyboard) that nano does not recognize. */
+ statusline(ALERT, _("Unknown sequence"));
+ suppress_cursorpos = FALSE;
+ lastmessage = HUSH;
+ if (currmenu == MMAIN) {
+ place_the_cursor();
+#ifdef __NetBSD__
+ wnoutrefresh(edit); /* Needed for correct placement on NetBSD. */
+#endif
+ curs_set(1);
+ }
+ }
+
+ return retval;
+}
+
+/* Extract a single keystroke from the input stream. Translate escape
+ * sequences and extended keypad codes into their corresponding values.
+ * Set meta_key to TRUE when appropriate. Supported extended keypad values
+ * are: [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
+ * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
+ * the function keys (F1-F16), and the numeric keypad with NumLock off. */
+int parse_kbinput(WINDOW *win)
+{
+ static int escapes = 0;
+ static bool double_esc = FALSE;
+ int *kbinput, keycode, retval = ERR;
+
+ meta_key = FALSE;
+ shift_held = FALSE;
+
+ /* Read in a character. */
+ kbinput = get_input(win, 1);
+
+ if (kbinput == NULL && !waiting_mode)
+ return ERR;
+
+ while (kbinput == NULL)
+ kbinput = get_input(win, 1);
+
+ keycode = *kbinput;
+ free(kbinput);
+
+ if (keycode == ERR)
+ return ERR;
+
+ if (keycode == ESC_CODE) {
+ /* Increment the escape counter, but trim an overabundance. */
+ escapes++;
+ if (escapes > 3)
+ escapes = 1;
+ /* Take note when an Esc arrived by itself. */
+ solitary = (key_buffer_len == 0);
+ return ERR;
+ }
+
+ switch (escapes) {
+ case 0:
+ /* One non-escape: normal input mode. */
+ retval = keycode;
+ break;
+ case 1:
+ if (keycode >= 0x80)
+ retval = keycode;
+ else if (keycode == TAB_CODE)
+ retval = SHIFT_TAB;
+ else if ((keycode != 'O' && keycode != 'o' && keycode != '[') ||
+ key_buffer_len == 0 || *key_buffer == ESC_CODE) {
+ /* One escape followed by a single non-escape:
+ * meta key sequence mode. */
+ if (!solitary || (keycode >= 0x20 && keycode < 0x7F))
+ meta_key = TRUE;
+ retval = (shifted_metas) ? keycode : tolower(keycode);
+ } else
+ /* One escape followed by a non-escape, and there
+ * are more codes waiting: escape sequence mode. */
+ retval = parse_escape_sequence(win, keycode);
+ escapes = 0;
+ break;
+ case 2:
+ if (double_esc) {
+ /* An "ESC ESC [ X" sequence from Option+arrow, or
+ * an "ESC ESC [ x" sequence from Shift+Alt+arrow. */
+ switch (keycode) {
+ case 'A':
+ retval = KEY_HOME;
+ break;
+ case 'B':
+ retval = KEY_END;
+ break;
+ case 'C':
+ retval = CONTROL_RIGHT;
+ break;
+ case 'D':
+ retval = CONTROL_LEFT;
+ break;
#ifndef NANO_TINY
- case 'F': /* Esc [ 1 ; 2 F == Shift-End on xterm. */
- return SHIFT_END;
- case 'H': /* Esc [ 1 ; 2 H == Shift-Home on xterm. */
- return SHIFT_HOME;
+ case 'a':
+ retval = shiftaltup;
+ break;
+ case 'b':
+ retval = shiftaltdown;
+ break;
+ case 'c':
+ retval = shiftaltright;
+ break;
+ case 'd':
+ retval = shiftaltleft;
+ break;
+#endif
+ }
+ double_esc = FALSE;
+ escapes = 0;
+ } else if (key_buffer_len == 0) {
+ if ('0' <= keycode && ((keycode <= '2' && digit_count == 0) ||
+ (keycode <= '9' && digit_count > 0))) {
+ /* Two escapes followed by one or more decimal
+ * digits, and there aren't any other codes
+ * waiting: byte sequence mode. If the range of the
+ * byte sequence is limited to 2XX, interpret it. */
+ int byte = get_byte_kbinput(keycode);
+
+ /* If the decimal byte value is complete, convert it and
+ * put the obtained byte(s) back into the input buffer. */
+ if (byte != ERR) {
+ char *multibyte;
+ int count, onebyte, i;
+
+ /* Convert the decimal code to one or two bytes. */
+ multibyte = make_mbchar((long)byte, &count);
+
+ /* Insert the byte(s) into the input buffer. */
+ for (i = count; i > 0 ; i--) {
+ onebyte = (unsigned char)multibyte[i - 1];
+ put_back(onebyte);
+ }
+
+ free(multibyte);
+
+ escapes = 0;
+ }
+ } else {
+ if (digit_count == 0)
+ /* Two escapes followed by a non-digit: meta key
+ * or control character sequence mode. */
+ if (!solitary) {
+ meta_key = TRUE;
+ retval = (shifted_metas) ? keycode : tolower(keycode);
+ } else
+ retval = get_control_kbinput(keycode);
+ else {
+ /* An invalid digit in the middle of a byte
+ * sequence: reset the byte sequence counter
+ * and save the code we got as the result. */
+ digit_count = 0;
+ retval = keycode;
+ }
+ escapes = 0;
+ }
+ } else if (keycode == '[' && key_buffer_len > 0 &&
+ (('A' <= *key_buffer && *key_buffer <= 'D') ||
+ ('a' <= *key_buffer && *key_buffer <= 'd'))) {
+ /* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */
+ double_esc = TRUE;
+ } else {
+ /* Two escapes followed by a non-escape, and there are more
+ * codes waiting: combined meta and escape sequence mode. */
+ retval = parse_escape_sequence(win, keycode);
+ meta_key = TRUE;
+ escapes = 0;
+ }
+ break;
+ case 3:
+ if (key_buffer_len == 0) {
+ if (!solitary) {
+ meta_key = TRUE;
+ retval = (shifted_metas) ? keycode : tolower(keycode);
+ } else
+ /* Three escapes followed by a non-escape, and no
+ * other codes are waiting: normal input mode. */
+ retval = keycode;
+ } else
+ /* Three escapes followed by a non-escape, and more
+ * codes are waiting: combined control character and
+ * escape sequence mode. First interpret the escape
+ * sequence, then the result as a control sequence. */
+ retval = get_control_kbinput(
+ parse_escape_sequence(win, keycode));
+ escapes = 0;
+ break;
+ }
+
+ if (retval == ERR)
+ return ERR;
+
+ if (retval == controlleft)
+ return CONTROL_LEFT;
+ else if (retval == controlright)
+ return CONTROL_RIGHT;
+ else if (retval == controlup)
+ return CONTROL_UP;
+ else if (retval == controldown)
+ return CONTROL_DOWN;
+ else if (retval == controlhome)
+ return CONTROL_HOME;
+ else if (retval == controlend)
+ return CONTROL_END;
+#ifndef NANO_TINY
+ else if (retval == controldelete)
+ return CONTROL_DELETE;
+ else if (retval == controlshiftdelete)
+ return CONTROL_SHIFT_DELETE;
+ else if (retval == shiftup) {
+ shift_held = TRUE;
+ return KEY_UP;
+ } else if (retval == shiftdown) {
+ shift_held = TRUE;
+ return KEY_DOWN;
+ } else if (retval == shiftcontrolleft) {
+ shift_held = TRUE;
+ return CONTROL_LEFT;
+ } else if (retval == shiftcontrolright) {
+ shift_held = TRUE;
+ return CONTROL_RIGHT;
+ } else if (retval == shiftcontrolup) {
+ shift_held = TRUE;
+ return CONTROL_UP;
+ } else if (retval == shiftcontroldown) {
+ shift_held = TRUE;
+ return CONTROL_DOWN;
+ } else if (retval == shiftcontrolhome) {
+ shift_held = TRUE;
+ return CONTROL_HOME;
+ } else if (retval == shiftcontrolend) {
+ shift_held = TRUE;
+ return CONTROL_END;
+ } else if (retval == altleft)
+ return ALT_LEFT;
+ else if (retval == altright)
+ return ALT_RIGHT;
+ else if (retval == altup)
+ return ALT_UP;
+ else if (retval == altdown)
+ return ALT_DOWN;
+ else if (retval == altdelete)
+ return ALT_DELETE;
+ else if (retval == shiftaltleft) {
+ shift_held = TRUE;
+ return KEY_HOME;
+ } else if (retval == shiftaltright) {
+ shift_held = TRUE;
+ return KEY_END;
+ } else if (retval == shiftaltup) {
+ shift_held = TRUE;
+ return KEY_PPAGE;
+ } else if (retval == shiftaltdown) {
+ shift_held = TRUE;
+ return KEY_NPAGE;
+ }
#endif
-#ifdef ENABLE_NANORC
- case 'P': /* Esc [ 1 ; 2 P == F13 on xterm. */
- case 'Q': /* Esc [ 1 ; 2 Q == F14 on xterm. */
- case 'R': /* Esc [ 1 ; 2 R == F15 on xterm. */
- case 'S': /* Esc [ 1 ; 2 S == F16 on xterm. */
- return KEY_F(13 + seq[4] - 'P');
+
+#ifdef __linux__
+ /* When not running under X, check for the bare arrow keys whether
+ * Shift/Ctrl/Alt are being held together with them. */
+ unsigned char modifiers = 6;
+
+ /* Modifiers are: Alt (8), Ctrl (4), Shift (1). */
+ if (on_a_vt && !mute_modifiers && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
+#ifndef NANO_TINY
+ /* Is Delete pressed together with Shift or Shift+Ctrl? */
+ if (retval == KEY_DC) {
+ if (modifiers == 0x01)
+ return SHIFT_DELETE;
+ if (modifiers == 0x05)
+ return CONTROL_SHIFT_DELETE;
+ }
+ /* Is Shift being held? */
+ if (modifiers & 0x01) {
+ if (retval == TAB_CODE)
+ return SHIFT_TAB;
+ if (!meta_key)
+ shift_held = TRUE;
+ }
+ /* Is Alt being held? */
+ if (modifiers == 0x08) {
+ if (retval == KEY_DC)
+ return ALT_DELETE;
+ if (retval == KEY_UP)
+ return ALT_UP;
+ if (retval == KEY_DOWN)
+ return ALT_DOWN;
+ }
#endif
- }
- break;
+ /* Is Ctrl being held? */
+ if (modifiers & 0x04) {
+ if (retval == KEY_UP)
+ return CONTROL_UP;
+ else if (retval == KEY_DOWN)
+ return CONTROL_DOWN;
+ else if (retval == KEY_LEFT)
+ return CONTROL_LEFT;
+ else if (retval == KEY_RIGHT)
+ return CONTROL_RIGHT;
+ else if (retval == KEY_HOME)
+ return CONTROL_HOME;
+ else if (retval == KEY_END)
+ return CONTROL_END;
+ else if (retval == KEY_DC)
+ return CONTROL_DELETE;
+ }
#ifndef NANO_TINY
- case '9': /* To accommodate iTerm2 in "xterm mode". */
- case '3':
- switch (seq[4]) {
- case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */
- return ALT_UP;
- case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */
- return ALT_DOWN;
- case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */
- return ALT_RIGHT;
- case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */
- return ALT_LEFT;
- }
- break;
- case '4':
- /* When the arrow keys are held together with Shift+Meta,
- * act as if they are Home/End/PgUp/PgDown with Shift. */
- switch (seq[4]) {
- case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */
- return SHIFT_PAGEUP;
- case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */
- return SHIFT_PAGEDOWN;
- case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */
- return SHIFT_END;
- case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */
- return SHIFT_HOME;
- }
- break;
+ /* Are both Shift and Alt being held? */
+ if ((modifiers & 0x09) == 0x09) {
+ if (retval == KEY_UP)
+ return KEY_PPAGE;
+ else if (retval == KEY_DOWN)
+ return KEY_NPAGE;
+ else if (retval == KEY_LEFT)
+ return KEY_HOME;
+ else if (retval == KEY_RIGHT)
+ return KEY_END;
+ }
#endif
- case '5':
- switch (seq[4]) {
- case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
- return CONTROL_UP;
- case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */
- return CONTROL_DOWN;
- case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */
- return CONTROL_RIGHT;
- case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */
- return CONTROL_LEFT;
- case 'F': /* Esc [ 1 ; 5 F == Ctrl-End on xterm. */
- return CONTROL_END;
- case 'H': /* Esc [ 1 ; 5 H == Ctrl-Home on xterm. */
- return CONTROL_HOME;
- }
- break;
+ }
+#endif /* __linux__ */
+
#ifndef NANO_TINY
- case '6':
- switch (seq[4]) {
- case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */
- return shiftcontrolup;
- case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */
- return shiftcontroldown;
- case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */
- return shiftcontrolright;
- case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */
- return shiftcontrolleft;
- case 'F': /* Esc [ 1 ; 6 F == Shift-Ctrl-End on xterm. */
- return shiftcontrolend;
- case 'H': /* Esc [ 1 ; 6 H == Shift-Ctrl-Home on xterm. */
- return shiftcontrolhome;
- }
- break;
+ /* When <Tab> is pressed while the mark is on, do an indent. */
+ if (retval == TAB_CODE && openfile->mark && currmenu == MMAIN &&
+ !bracketed_paste && openfile->mark != openfile->current)
+ return INDENT_KEY;
#endif
- }
- /* ->->->->->->-> */
- } else if (length > 5 && seq[3] == ';' && seq[5] == '~')
- /* Esc [ 1 n ; 2 ~ == F17...F20 on some terminals. */
- *consumed = 6;
-#ifdef USE_SLANG
- else if (length == 4 && seq[3] == ';')
- /* Discard broken sequences that Slang produces. */
- *consumed = 4;
+
+ switch (retval) {
+#ifdef KEY_SLEFT /* Slang doesn't support KEY_SLEFT. */
+ case KEY_SLEFT:
+ shift_held = TRUE;
+ return KEY_LEFT;
#endif
- break;
- case '2':
- if (length > 3 && seq[3] == '~') {
- *consumed = 4;
- switch (seq[2]) {
- case '0': /* Esc [ 2 0 ~ == F9 on VT220/VT320/
- * Linux console/xterm/rxvt/Eterm. */
- return KEY_F(9);
- case '1': /* Esc [ 2 1 ~ == F10 on the same. */
- return KEY_F(10);
- case '3': /* Esc [ 2 3 ~ == F11 on the same. */
- return KEY_F(11);
- case '4': /* Esc [ 2 4 ~ == F12 on the same. */
- return KEY_F(12);
-#ifdef ENABLE_NANORC
- case '5': /* Esc [ 2 5 ~ == F13 on VT220/VT320/
- * Linux console/rxvt/Eterm. */
- return KEY_F(13);
- case '6': /* Esc [ 2 6 ~ == F14 on the same. */
- return KEY_F(14);
- case '8': /* Esc [ 2 8 ~ == F15 on the same. */
- return KEY_F(15);
- case '9': /* Esc [ 2 9 ~ == F16 on the same. */
- return KEY_F(16);
+#ifdef KEY_SRIGHT /* Slang doesn't support KEY_SRIGHT. */
+ case KEY_SRIGHT:
+ shift_held = TRUE;
+ return KEY_RIGHT;
#endif
- }
- } else if (length > 2 && seq[2] == '~')
- /* Esc [ 2 ~ == Insert on VT220/VT320/
- * Linux console/xterm/Terminal. */
- return KEY_IC;
- else if (length > 4 && seq[2] == ';' && seq[4] == '~')
- /* Esc [ 2 ; x ~ == modified Insert on xterm. */
- *consumed = 5;
- else if (length > 5 && seq[3] == ';' && seq[5] == '~')
- /* Esc [ 2 n ; 2 ~ == F21...F24 on some terminals. */
- *consumed = 6;
-#ifdef USE_SLANG
- else if (length == 4 && seq[3] == ';')
- /* Discard broken sequences that Slang produces. */
- *consumed = 4;
+#ifdef KEY_SR
+#ifdef KEY_SUP /* ncurses and Slang don't support KEY_SUP. */
+ case KEY_SUP:
#endif
-#ifndef NANO_TINY
- else if (length > 4 && seq[2] == '0' && seq[4] == '~') {
- /* Esc [ 2 0 0 ~ == start of a bracketed paste,
- * Esc [ 2 0 1 ~ == end of a bracketed paste. */
- *consumed = 5;
- if (seq[3] == '0') {
- bracketed_paste = TRUE;
- return BRACKETED_PASTE_MARKER;
- } else if (seq[3] == '1') {
- bracketed_paste = FALSE;
- return BRACKETED_PASTE_MARKER;
- }
- }
+ case KEY_SR: /* Scroll backward, on Xfce4-terminal. */
+ shift_held = TRUE;
+ return KEY_UP;
#endif
- break;
- case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
- * Linux console/xterm/Terminal. */
- if (length > 2 && seq[2] == '~')
- return KEY_DC;
- if (length > 4 && seq[2] == ';' && seq[4] == '~') {
- *consumed = 5;
-#ifndef NANO_TINY
- if (seq[3] == '2')
- /* Esc [ 3 ; 2 ~ == Shift-Delete on xterm/Terminal. */
- return SHIFT_DELETE;
- if (seq[3] == '3')
- /* Esc [ 3 ; 3 ~ == Alt-Delete on xterm/rxvt/Eterm/Terminal. */
- return ALT_DELETE;
- if (seq[3] == '5')
- /* Esc [ 3 ; 5 ~ == Ctrl-Delete on xterm. */
- return CONTROL_DELETE;
- if (seq[3] == '6')
- /* Esc [ 3 ; 6 ~ == Ctrl-Shift-Delete on xterm. */
- return controlshiftdelete;
+#ifdef KEY_SF
+#ifdef KEY_SDOWN /* ncurses and Slang don't support KEY_SDOWN. */
+ case KEY_SDOWN:
+#endif
+ case KEY_SF: /* Scroll forward, on Xfce4-terminal. */
+ shift_held = TRUE;
+ return KEY_DOWN;
+#endif
+#ifdef KEY_SHOME /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
+ case KEY_SHOME:
+#endif
+ case SHIFT_HOME:
+ shift_held = TRUE;
+ case KEY_A1: /* Home (7) on keypad with NumLock off. */
+ return KEY_HOME;
+#ifdef KEY_SEND /* HP-UX 10-11 and Slang don't support KEY_SEND. */
+ case KEY_SEND:
+#endif
+ case SHIFT_END:
+ shift_held = TRUE;
+ case KEY_C1: /* End (1) on keypad with NumLock off. */
+ return KEY_END;
+#ifdef KEY_EOL
+ case KEY_EOL: /* Ctrl+End on rxvt-unicode. */
+ return CONTROL_END;
#endif
- }
#ifndef NANO_TINY
- if (length > 2 && seq[2] == '$')
- /* Esc [ 3 $ == Shift-Delete on urxvt. */
- return SHIFT_DELETE;
- if (length > 2 && seq[2] == '^')
- /* Esc [ 3 ^ == Ctrl-Delete on urxvt. */
- return CONTROL_DELETE;
- if (length > 2 && seq[2] == '@')
- /* Esc [ 3 @ == Ctrl-Shift-Delete on urxvt. */
- return controlshiftdelete;
- if (length > 3 && seq[3] == '~')
- /* Esc [ 3 n ~ == F17...F20 on some terminals. */
- *consumed = 4;
+#ifdef KEY_SPREVIOUS
+ case KEY_SPREVIOUS:
#endif
- break;
- case '4': /* Esc [ 4 ~ == End on VT220/VT320/
- * Linux console/xterm. */
- if (length > 2 && seq[2] == '~')
- return KEY_END;
- break;
- case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
- * Linux console/xterm/Eterm/urxvt/Terminal */
- if (length > 2 && seq[2] == '~')
- return KEY_PPAGE;
- else if (length > 4 && seq[2] == ';' && seq[4] == '~') {
- *consumed = 5;
-#ifndef NANO_TINY
- if (seq[3] == '2')
- return shiftaltup;
+ case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */
+ shift_held = TRUE;
#endif
- }
- break;
- case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
- * Linux console/xterm/Eterm/urxvt/Terminal */
- if (length > 2 && seq[2] == '~')
- return KEY_NPAGE;
- else if (length > 4 && seq[2] == ';' && seq[4] == '~') {
- *consumed = 5;
+ case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
+ return KEY_PPAGE;
#ifndef NANO_TINY
- if (seq[3] == '2')
- return shiftaltdown;
+#ifdef KEY_SNEXT
+ case KEY_SNEXT:
#endif
- }
- break;
- case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt;
- * Esc [ 7 $ == Shift-Home on Eterm/rxvt;
- * Esc [ 7 ^ == Control-Home on Eterm/rxvt;
- * Esc [ 7 @ == Shift-Control-Home on same. */
- if (length > 2 && seq[2] == '~')
- return KEY_HOME;
- else if (length > 2 && seq[2] == '$')
- return SHIFT_HOME;
- else if (length > 2 && seq[2] == '^')
- return CONTROL_HOME;
-#ifndef NANO_TINY
- else if (length > 2 && seq[2] == '@')
- return shiftcontrolhome;
+ case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */
+ shift_held = TRUE;
#endif
- break;
- case '8': /* Esc [ 8 ~ == End on Eterm/rxvt;
- * Esc [ 8 $ == Shift-End on Eterm/rxvt;
- * Esc [ 8 ^ == Control-End on Eterm/rxvt;
- * Esc [ 8 @ == Shift-Control-End on same. */
- if (length > 2 && seq[2] == '~')
- return KEY_END;
- else if (length > 2 && seq[2] == '$')
- return SHIFT_END;
- else if (length > 2 && seq[2] == '^')
- return CONTROL_END;
-#ifndef NANO_TINY
- else if (length > 2 && seq[2] == '@')
- return shiftcontrolend;
+ case KEY_C3: /* PageDown (3) on keypad with NumLock off. */
+ return KEY_NPAGE;
+ /* When requested, swap meanings of keycodes for <Bsp> and <Del>. */
+ case DEL_CODE:
+ case KEY_BACKSPACE:
+ return (ISSET(REBIND_DELETE) ? KEY_DC : KEY_BACKSPACE);
+ case KEY_DC:
+ return (ISSET(REBIND_DELETE) ? KEY_BACKSPACE : KEY_DC);
+#ifdef KEY_SDC /* Slang doesn't support KEY_SDC. */
+ case KEY_SDC:
+ return SHIFT_DELETE;
#endif
- break;
- case '9': /* Esc [ 9 == Delete on Mach console. */
- return KEY_DC;
- case '@': /* Esc [ @ == Insert on Mach console. */
- return KEY_IC;
- case 'A': /* Esc [ A == Up on ANSI/VT220/Linux console/
- * FreeBSD console/Mach console/xterm/Eterm/
- * urxvt/Gnome and Xfce Terminal. */
- case 'B': /* Esc [ B == Down on the same. */
- case 'C': /* Esc [ C == Right on the same. */
- case 'D': /* Esc [ D == Left on the same. */
- return arrow_from_ABCD(seq[1]);
- case 'F': /* Esc [ F == End on FreeBSD console/Eterm. */
- return KEY_END;
- case 'G': /* Esc [ G == PageDown on FreeBSD console. */
- return KEY_NPAGE;
- case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
- * console/Mach console/Eterm. */
- return KEY_HOME;
- case 'I': /* Esc [ I == PageUp on FreeBSD console. */
- return KEY_PPAGE;
- case 'L': /* Esc [ L == Insert on ANSI/FreeBSD console. */
- return KEY_IC;
- case 'M': /* Esc [ M == F1 on FreeBSD console. */
- return KEY_F(1);
- case 'N': /* Esc [ N == F2 on FreeBSD console. */
- return KEY_F(2);
- case 'O':
- if (length > 2) {
- *consumed = 3;
- if ('O' < seq[2] && seq[2] < 'T')
- /* Esc [ O P == F1 on xterm. */
- /* Esc [ O Q == F2 on xterm. */
- /* Esc [ O R == F3 on xterm. */
- /* Esc [ O S == F4 on xterm. */
- return KEY_F(seq[2] - 'O');
- } else
- /* Esc [ O == F3 on FreeBSD console. */
- return KEY_F(3);
- break;
- case 'P': /* Esc [ P == F4 on FreeBSD console. */
- case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
- case 'R': /* Esc [ R == F6 on FreeBSD console. */
- case 'S': /* Esc [ S == F7 on FreeBSD console. */
- case 'T': /* Esc [ T == F8 on FreeBSD console. */
- return KEY_F(4 + seq[1] - 'P');
- case 'U': /* Esc [ U == PageDown on Mach console. */
- return KEY_NPAGE;
- case 'V': /* Esc [ V == PageUp on Mach console. */
- return KEY_PPAGE;
- case 'W': /* Esc [ W == F11 on FreeBSD console. */
- return KEY_F(11);
- case 'X': /* Esc [ X == F12 on FreeBSD console. */
- return KEY_F(12);
- case 'Y': /* Esc [ Y == End on Mach console. */
- return KEY_END;
- case 'Z': /* Esc [ Z == Shift-Tab on ANSI/Linux console/
- * FreeBSD console/xterm/rxvt/Terminal. */
- return SHIFT_TAB;
- case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
- case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
- case 'c': /* Esc [ c == Shift-Right on rxvt/Eterm. */
- case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
- shift_held = TRUE;
- return arrow_from_ABCD(toupper(seq[1]));
- case '[':
- if (length > 2) {
- *consumed = 3;
- if ('@' < seq[2] && seq[2] < 'F')
- /* Esc [ [ A == F1 on Linux console. */
- /* Esc [ [ B == F2 on Linux console. */
- /* Esc [ [ C == F3 on Linux console. */
- /* Esc [ [ D == F4 on Linux console. */
- /* Esc [ [ E == F5 on Linux console. */
- return KEY_F(seq[2] - '@');
- }
- break;
- }
- break;
- }
- }
-
- return ERR;
-}
-
-/* Interpret the escape sequence in the keystroke buffer, the first
- * character of which is kbinput. Assume that the keystroke buffer
- * isn't empty, and that the initial escape has already been read in. */
-int parse_escape_sequence(WINDOW *win, int kbinput)
-{
- int retval, *sequence, length, consumed;
-
- /* Put back the non-escape code, then grab at most six integers
- * (the longest possible escape sequence) from the keybuffer and
- * translate the sequence into its corresponding keycode. */
- put_back(kbinput);
- length = (key_buffer_len < 6 ? key_buffer_len : 6);
- sequence = get_input(NULL, length);
- retval = convert_sequence(sequence, length, &consumed);
-
- /* If not all grabbed integers were consumed, put the leftovers back. */
- for (int i = length - 1; i >= consumed; i--)
- put_back(sequence[i]);
-
- free(sequence);
-
- /* If we got an unrecognized escape sequence, notify the user. */
- if (retval == ERR && win == edit) {
- /* TRANSLATORS: This refers to a sequence of escape codes
- * (from the keyboard) that nano does not recognize. */
- statusline(ALERT, _("Unknown sequence"));
- suppress_cursorpos = FALSE;
- lastmessage = HUSH;
- if (currmenu == MMAIN) {
- place_the_cursor();
-#ifdef __NetBSD__
- wnoutrefresh(edit); /* Needed for correct placement on NetBSD. */
+#ifdef KEY_SIC /* Slang doesn't support KEY_SIC. */
+ case KEY_SIC:
+ return the_code_for(do_insertfile_void, KEY_IC);
#endif
- curs_set(1);
- }
+#ifdef KEY_CANCEL /* Slang doesn't support KEY_CANCEL. */
+#ifdef KEY_SCANCEL /* Slang doesn't support KEY_SCANCEL. */
+ case KEY_SCANCEL:
+#endif
+ case KEY_CANCEL:
+ return the_code_for(do_cancel, 0x03);
+#endif
+#ifdef KEY_SUSPEND /* Slang doesn't support KEY_SUSPEND. */
+#ifdef KEY_SSUSPEND /* Slang doesn't support KEY_SSUSPEND. */
+ case KEY_SSUSPEND:
+#endif
+ case KEY_SUSPEND:
+ return the_code_for(do_suspend_void, KEY_SUSPEND);
+#endif
+#ifdef KEY_BTAB /* Slang doesn't support KEY_BTAB. */
+ case KEY_BTAB:
+ return SHIFT_TAB;
+#endif
+#ifdef KEY_SBEG /* Slang doesn't support KEY_SBEG. */
+ case KEY_SBEG:
+#endif
+#ifdef KEY_BEG /* Slang doesn't support KEY_BEG. */
+ case KEY_BEG:
+#endif
+ case KEY_B2: /* Center (5) on keypad with NumLock off. */
+#ifdef PDCURSES
+ case KEY_SHIFT_L:
+ case KEY_SHIFT_R:
+ case KEY_CONTROL_L:
+ case KEY_CONTROL_R:
+ case KEY_ALT_L:
+ case KEY_ALT_R:
+#endif
+#ifdef KEY_RESIZE /* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
+ case KEY_RESIZE:
+#endif
+#if defined(USE_SLANG) && defined(ENABLE_UTF8)
+ case KEY_BAD:
+#endif
+ case KEY_FLUSH:
+ return ERR; /* Ignore this keystroke. */
}
return retval;