Commit 48ae9867 authored by David Lawrence Ramsey's avatar David Lawrence Ramsey
Browse files

refactor the low-level input routines into main routines that get the

input and state machines that interpret the input


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1773 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
parent d12fd4b1
Showing with 706 additions and 387 deletions
+706 -387
...@@ -65,6 +65,17 @@ CVS code - ...@@ -65,6 +65,17 @@ CVS code -
suggested by Stephan T. Lavavej) suggested by Stephan T. Lavavej)
- Minor tweaks to the punctuation in some statusbar messages. - Minor tweaks to the punctuation in some statusbar messages.
(DLR) (DLR)
- Overhaul the low-level input routines into main routines that
actually get the input and state machines that interpret the
input. This allows better handling of the input (e.g. ignored
keys are now always ignored instead of just being ignored when
there are no escapes prefixing them) and will make it easier
to port to interfaces that don't have blocking input. New
functions reset_kbinput(), get_translated_kbinput(),
get_control_kbinput(), and get_untranslated_kbinput(); changes
to do_verbatim_input(), handle_sigwinch(), get_kbinput(),
get_ascii_kbinput(), get_escape_seq_kbinput(), and
get_verbatim_kbinput(). (DLR)
- files.c: - files.c:
add_open_file() add_open_file()
- Rearrange the NANO_SMALL #ifdef so that the code to set the - Rearrange the NANO_SMALL #ifdef so that the code to set the
......
...@@ -982,22 +982,23 @@ void do_char(char ch) ...@@ -982,22 +982,23 @@ void do_char(char ch)
int do_verbatim_input(void) int do_verbatim_input(void)
{ {
int *verbatim_kbinput; /* Used to hold verbatim input. */ int *v_kbinput = NULL; /* Used to hold verbatim input. */
size_t verbatim_len; /* Length of verbatim input. */ size_t v_len; /* Length of verbatim input. */
size_t i; size_t i;
statusbar(_("Verbatim input")); statusbar(_("Verbatim input"));
verbatim_kbinput = get_verbatim_kbinput(edit, &verbatim_len, 1);
v_kbinput = get_verbatim_kbinput(edit, v_kbinput, &v_len, TRUE);
/* Turn on DISABLE_CURPOS while inserting character(s) and turn it /* Turn on DISABLE_CURPOS while inserting character(s) and turn it
* off afterwards, so that if constant cursor position display is * off afterwards, so that if constant cursor position display is
* on, it will be updated properly. */ * on, it will be updated properly. */
SET(DISABLE_CURPOS); SET(DISABLE_CURPOS);
for (i = 0; i < verbatim_len; i++) for (i = 0; i < v_len; i++)
do_char((char)verbatim_kbinput[i]); do_char((char)v_kbinput[i]);
UNSET(DISABLE_CURPOS); UNSET(DISABLE_CURPOS);
free(verbatim_kbinput); free(v_kbinput);
return 1; return 1;
} }
...@@ -2876,6 +2877,9 @@ void handle_sigwinch(int s) ...@@ -2876,6 +2877,9 @@ void handle_sigwinch(int s)
/* Restore the terminal to its previously saved state. */ /* Restore the terminal to its previously saved state. */
resetty(); resetty();
/* Reset all the input routines that rely on character sequences. */
reset_kbinput();
/* Jump back to the main loop. */ /* Jump back to the main loop. */
siglongjmp(jmpbuf, 1); siglongjmp(jmpbuf, 1);
} }
......
...@@ -467,15 +467,31 @@ int check_wildcard_match(const char *text, const char *pattern); ...@@ -467,15 +467,31 @@ int check_wildcard_match(const char *text, const char *pattern);
#endif #endif
/* Public functions in winio.c */ /* Public functions in winio.c */
#ifndef NANO_SMALL
void reset_kbinput(void);
#endif
int get_kbinput(WINDOW *win, int *meta_key); int get_kbinput(WINDOW *win, int *meta_key);
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len, int int get_translated_kbinput(int kbinput, int *es
allow_ascii); #ifndef NANO_SMALL
int get_ignored_kbinput(WINDOW *win); , int reset
int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta_key); #endif
int get_ascii_kbinput(WINDOW *win, int kbinput); );
int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t int get_ascii_kbinput(int kbinput, size_t ascii_digits
escape_seq_len); #ifndef NANO_SMALL
, int reset
#endif
);
int get_control_kbinput(int kbinput);
int get_escape_seq_kbinput(int *escape_seq, size_t es_len);
int get_escape_seq_abcd(int kbinput); int get_escape_seq_abcd(int kbinput);
int *get_verbatim_kbinput(WINDOW *win, int *verbatim_kbinput, size_t
*verbatim_len, int allow_ascii);
int get_untranslated_kbinput(int kbinput, size_t position, int
allow_ascii
#ifndef NANO_SMALL
, int reset
#endif
);
#ifndef DISABLE_MOUSE #ifndef DISABLE_MOUSE
int get_mouseinput(int *mouse_x, int *mouse_y, int shortcut); int get_mouseinput(int *mouse_x, int *mouse_y, int shortcut);
#endif #endif
......
...@@ -72,8 +72,7 @@ static int statblank = 0; /* Number of keystrokes left after ...@@ -72,8 +72,7 @@ static int statblank = 0; /* Number of keystrokes left after
* - PageDown on FreeBSD console == Center (5) on numeric keypad with * - PageDown on FreeBSD console == Center (5) on numeric keypad with
* NumLock off on Linux console; the latter is omitted. (The editing * NumLock off on Linux console; the latter is omitted. (The editing
* keypad key is more important to have working than the numeric * keypad key is more important to have working than the numeric
* keypad key, because the latter actually has no value when NumLock * keypad key, because the latter has no value when NumLock is off.)
* is off.)
* - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
* latter is omitted. (Mouse input will only work properly if the * latter is omitted. (Mouse input will only work properly if the
* extended keypad value KEY_MOUSE is generated on mouse events * extended keypad value KEY_MOUSE is generated on mouse events
...@@ -92,353 +91,475 @@ static int statblank = 0; /* Number of keystrokes left after ...@@ -92,353 +91,475 @@ static int statblank = 0; /* Number of keystrokes left after
* Note that Center (5) on the numeric keypad with NumLock off can also * Note that Center (5) on the numeric keypad with NumLock off can also
* be the Begin key. */ * be the Begin key. */
#ifndef NANO_SMALL
/* Reset all the input routines that rely on character sequences. */
void reset_kbinput(void)
{
get_translated_kbinput(0, NULL, TRUE);
get_ascii_kbinput(0, 0, TRUE);
get_untranslated_kbinput(0, 0, FALSE, TRUE);
}
#endif
/* Read in a single input character. If it's ignored, swallow it and go /* Read in a single input character. If it's ignored, swallow it and go
* on. Otherwise, try to translate it from ASCII, extended keypad * on. Otherwise, try to translate it from ASCII, extended keypad
* values, and/or escape sequences. Supported extended keypad values * values, and/or escape sequences. Set meta_key to TRUE when we get a
* consist of [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, * meta sequence. Supported extended keypad values consist of [arrow
* Backspace, the editing keypad (Insert, Delete, Home, End, PageUp, and * key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace, the
* PageDown), the function keypad (F1-F14), and the numeric keypad with * editing keypad (Insert, Delete, Home, End, PageUp, and PageDown), the
* NumLock off. Assume nodelay(win) is FALSE. */ * function keypad (F1-F14), and the numeric keypad with NumLock off.
* Assume nodelay(win) is FALSE. */
int get_kbinput(WINDOW *win, int *meta_key) int get_kbinput(WINDOW *win, int *meta_key)
{ {
int kbinput, retval; int kbinput, es, retval = ERR;
#ifndef NANO_SMALL #ifndef NANO_SMALL
allow_pending_sigwinch(TRUE); allow_pending_sigwinch(TRUE);
#endif #endif
kbinput = get_ignored_kbinput(win); *meta_key = FALSE;
retval = get_accepted_kbinput(win, kbinput, meta_key);
#ifndef NANO_SMALL
allow_pending_sigwinch(FALSE);
#endif
return retval;
}
/* Read in a string of input characters (e.g. an escape sequence)
* verbatim, and return the length of the string in kbinput_len. Assume
* nodelay(win) is FALSE. */
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len, int
allow_ascii)
{
int kbinput, *verbatim_kbinput;
while (retval == ERR) {
/* Read a character using blocking input, since using
* non-blocking input will eat up all unused CPU. Then pass it
* to get_translated_kbinput(). Continue until we get a
* complete sequence. */
kbinput = wgetch(win);
retval = get_translated_kbinput(kbinput, &es
#ifndef NANO_SMALL #ifndef NANO_SMALL
allow_pending_sigwinch(TRUE); , FALSE
#endif #endif
);
/* Turn off flow control characters if necessary so that we can type /* If we got an escape sequence, read it in, including the
* them in verbatim, and turn the keypad off so that we don't get * initial non-escape, as verbatim input. */
* extended keypad values outside the ASCII range. */ if (es) {
if (ISSET(PRESERVE)) int *escape_seq = NULL;
disable_flow_control(); size_t es_len;
keypad(win, FALSE);
/* First, assume that we got a meta sequence. Set meta_key
kbinput = wgetch(win); * to TRUE and save the character we got as the result. We
verbatim_kbinput = (int *)nmalloc(sizeof(int)); * do this so that if there's a delay greater than nodelay()
verbatim_kbinput[0] = kbinput; * between Escape and the character we got (after we
*kbinput_len = 1; * ungetch() it below), it'll still be properly interpreted
* as a meta sequence. */
if (allow_ascii && kbinput >= '0' && kbinput <= '2') *meta_key = TRUE;
/* Entering a three-digit decimal ASCII code from 000-255 in retval = tolower(kbinput);
* verbatim mode will produce the corresponding ASCII
* character. */ /* Next, send back the character we got and read in the
verbatim_kbinput[0] = get_ascii_kbinput(win, kbinput); * complete escape sequence. */
else { ungetch(kbinput);
nodelay(win, TRUE); escape_seq = get_verbatim_kbinput(win, escape_seq, &es_len,
#ifdef DEBUG FALSE);
fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d\n", kbinput);
#endif if (es_len > 1) {
while ((kbinput = wgetch(win)) != ERR) { /* The escape sequence is more than one character
(*kbinput_len)++; * long. Set meta_key to FALSE, translate the escape
verbatim_kbinput = (int *)nrealloc(verbatim_kbinput, *kbinput_len * sizeof(int)); * sequence into the corresponding key value, and save
verbatim_kbinput[*kbinput_len - 1] = kbinput; * that as the result. */
#ifdef DEBUG *meta_key = FALSE;
fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d\n", kbinput); if ((retval = get_escape_seq_kbinput(escape_seq,
#endif es_len)) == ERR) {
/* This escape sequence is unrecognized. Send it
* back. */
for (; es_len > 1; es_len--)
ungetch(escape_seq[es_len - 1]);
retval = escape_seq[0];
}
}
free(escape_seq);
} }
nodelay(win, FALSE);
} }
/* Turn flow control characters back on if necessary and turn the #ifdef DEBUG
* keypad back on now that we're done. */ fprintf(stderr, "get_kbinput(): kbinput = %d, meta_key = %d\n", kbinput, *meta_key);
if (ISSET(PRESERVE)) #endif
enable_flow_control();
keypad(win, TRUE);
#ifndef NANO_SMALL #ifndef NANO_SMALL
allow_pending_sigwinch(FALSE); allow_pending_sigwinch(FALSE);
#endif #endif
return verbatim_kbinput; return retval;
} }
/* Swallow input characters that should be quietly ignored, and return /* Translate acceptable ASCII, extended keypad values, and escape
* the first input character that shouldn't be. */ * sequences into their corresponding key values. Set es to TRUE when
int get_ignored_kbinput(WINDOW *win) * we get an escape sequence. Assume nodelay(win) is FALSE. */
int get_translated_kbinput(int kbinput, int *es
#ifndef NANO_SMALL
, int reset
#endif
)
{ {
int kbinput; static size_t escapes = 0, ascii_digits = 0;
int retval = ERR;
while (TRUE) { #ifndef NANO_SMALL
kbinput = wgetch(win); if (reset) {
switch (kbinput) { escapes = 0;
case ERR: ascii_digits = 0;
#ifdef KEY_RESIZE return ERR;
/* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
case KEY_RESIZE:
#endif
#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 DEBUG
fprintf(stderr, "get_ignored_kbinput(): kbinput = %d\n", kbinput);
#endif
break;
default:
return kbinput;
}
} }
} #endif
/* Translate acceptable ASCII, extended keypad values, and/or escape *es = FALSE;
* sequences. Set meta_key to 1 if we get a Meta sequence. Assume
* nodelay(win) is FALSE. */
int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta_key)
{
*meta_key = FALSE;
switch (kbinput) { switch (kbinput) {
case NANO_CONTROL_3: /* Escape */ case ERR:
kbinput = wgetch(win); break;
switch (kbinput) { case NANO_CONTROL_3:
case NANO_CONTROL_3: /* Escape */ /* Increment the escape counter. */
kbinput = wgetch(win); escapes++;
/* Esc Esc [three-digit decimal ASCII code from switch (escapes) {
* 000-255] == [corresponding ASCII character]; case 1:
* Esc Esc 2 obviously can't be Ctrl-2 here */ /* One escape: wait for more input. */
if (kbinput >= '0' && kbinput <= '2') case 2:
kbinput = get_ascii_kbinput(win, kbinput); /* Two escapes: wait for more input. */
/* Esc Esc [character] == Ctrl-[character];
* Ctrl-Space (Ctrl-2) == Ctrl-@ == Ctrl-` */
else if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
kbinput = NANO_CONTROL_SPACE;
/* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
else if (kbinput >= '3' && kbinput <= '7')
kbinput -= 24;
/* Ctrl-8 (Ctrl-?) */
else if (kbinput == '8' || kbinput == '?')
kbinput = NANO_CONTROL_8;
/* Ctrl-A to Ctrl-_ */
else if (kbinput >= 'A' && kbinput <= '_')
kbinput -= 64;
/* Ctrl-A to Ctrl-~ */
else if (kbinput >= 'a' && kbinput <= '~')
kbinput -= 96;
break;
case 'O':
case 'o':
case '[':
{
int old_kbinput = kbinput, *escape_seq;
size_t escape_seq_len;
nodelay(win, TRUE);
kbinput = wgetch(win);
switch (kbinput) {
case ERR:
kbinput = tolower(old_kbinput);
*meta_key = TRUE;
break;
default:
ungetch(kbinput);
ungetch(old_kbinput);
escape_seq = get_verbatim_kbinput(win, &escape_seq_len, 0);
kbinput = get_escape_seq_kbinput(win, escape_seq, escape_seq_len);
free(escape_seq);
}
nodelay(win, FALSE);
break; break;
}
default: default:
/* Esc [character] == Meta-[character] */ /* More than two escapes: reset the escape counter
kbinput = tolower(kbinput); * and wait for more input. */
*meta_key = TRUE; escapes = 0;
} }
break; break;
case NANO_CONTROL_8: #if !defined(NANO_SMALL) && defined(KEY_RESIZE)
kbinput = ISSET(REBIND_DELETE) ? NANO_DELETE_KEY : NANO_BACKSPACE_KEY; /* Since we don't change the default SIGWINCH handler when
break; * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
case KEY_DOWN: * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
kbinput = NANO_NEXTLINE_KEY; case KEY_RESIZE:
break; #endif
case KEY_UP: #ifdef PDCURSES
kbinput = NANO_PREVLINE_KEY; case KEY_SHIFT_L:
break; case KEY_SHIFT_R:
case KEY_LEFT: case KEY_CONTROL_L:
kbinput = NANO_BACK_KEY; case KEY_CONTROL_R:
break; case KEY_ALT_L:
case KEY_RIGHT: case KEY_ALT_R:
kbinput = NANO_FORWARD_KEY; #endif
retval = ERR;
break; break;
default:
switch (escapes) {
case 0:
switch (kbinput) {
case NANO_CONTROL_8:
retval = ISSET(REBIND_DELETE) ?
NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
break;
case KEY_DOWN:
retval = NANO_NEXTLINE_KEY;
break;
case KEY_UP:
retval = NANO_PREVLINE_KEY;
break;
case KEY_LEFT:
retval = NANO_BACK_KEY;
break;
case KEY_RIGHT:
retval = NANO_FORWARD_KEY;
break;
#ifdef KEY_HOME #ifdef KEY_HOME
/* HP-UX 10 and 11 don't support KEY_HOME. */ /* HP-UX 10 and 11 don't support KEY_HOME. */
case KEY_HOME: case KEY_HOME:
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
#endif #endif
case KEY_BACKSPACE: case KEY_BACKSPACE:
kbinput = NANO_BACKSPACE_KEY; retval = NANO_BACKSPACE_KEY;
break; break;
case KEY_DC: case KEY_DC:
kbinput = ISSET(REBIND_DELETE) ? NANO_BACKSPACE_KEY : NANO_DELETE_KEY; retval = ISSET(REBIND_DELETE) ?
break; NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
case KEY_IC: break;
kbinput = NANO_INSERTFILE_KEY; case KEY_IC:
break; retval = NANO_INSERTFILE_KEY;
case KEY_NPAGE: break;
kbinput = NANO_NEXTPAGE_KEY; case KEY_NPAGE:
break; retval = NANO_NEXTPAGE_KEY;
case KEY_PPAGE: break;
kbinput = NANO_PREVPAGE_KEY; case KEY_PPAGE:
break; retval = NANO_PREVPAGE_KEY;
case KEY_ENTER: break;
kbinput = NANO_ENTER_KEY; case KEY_ENTER:
break; retval = NANO_ENTER_KEY;
case KEY_B2: /* Center (5) on numeric keypad with NumLock off break;
* on xterm. */ case KEY_B2: /* Center (5) on numeric keypad
* with NumLock off on xterm. */
#ifdef KEY_BEG #ifdef KEY_BEG
/* Slang doesn't support KEY_BEG. */ /* Slang doesn't support KEY_BEG. */
case KEY_BEG: /* Center (5) on numeric keypad with NumLock off case KEY_BEG: /* Center (5) on numeric keypad
* on Eterm. */ * with NumLock off on Eterm. */
#endif #endif
kbinput = '5'; retval = ERR;
break; break;
#ifdef KEY_END #ifdef KEY_END
/* HP-UX 10 and 11 don't support KEY_END. */ /* HP-UX 10 and 11 don't support KEY_END. */
case KEY_END: case KEY_END:
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
#endif #endif
#ifdef KEY_SUSPEND #ifdef KEY_SUSPEND
/* Slang doesn't support KEY_SUSPEND. */ /* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND: case KEY_SUSPEND:
kbinput = NANO_SUSPEND_KEY; retval = NANO_SUSPEND_KEY;
break; break;
#endif #endif
#ifdef KEY_SLEFT #ifdef KEY_SLEFT
/* Slang doesn't support KEY_SLEFT. */ /* Slang doesn't support KEY_SLEFT. */
case KEY_SLEFT: case KEY_SLEFT:
kbinput = NANO_BACK_KEY; retval = NANO_BACK_KEY;
break; break;
#endif #endif
#ifdef KEY_SRIGHT #ifdef KEY_SRIGHT
/* Slang doesn't support KEY_SRIGHT. */ /* Slang doesn't support KEY_SRIGHT. */
case KEY_SRIGHT: case KEY_SRIGHT:
kbinput = NANO_FORWARD_KEY; retval = NANO_FORWARD_KEY;
break; break;
#endif #endif
default:
retval = kbinput;
break;
}
break;
case 1:
/* One escape followed by a non-escape: escape
* sequence mode. Reset the escape counter and set
* es to TRUE. */
escapes = 0;
*es = TRUE;
break;
case 2:
switch (kbinput) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* Two escapes followed by one or more
* digits: ASCII character sequence mode.
* If the digit sequence's range is limited
* to 2XX (the first digit is in the '0' to
* '2' range and it's the first digit, or if
* it's in the full digit range and it's not
* the first digit), increment the ASCII
* digit counter and interpret the digit.
* If the digit sequence's range is not
* limited to 2XX, fall through. */
if (kbinput <= '2' || ascii_digits > 0) {
ascii_digits++;
kbinput = get_ascii_kbinput(kbinput,
ascii_digits
#ifndef NANO_SMALL
, FALSE
#endif
);
if (kbinput != ERR) {
/* If we've read in a complete ASCII
* digit sequence, reset the ASCII
* digit counter and the escape
* counter and save the corresponding
* ASCII character as the result. */
ascii_digits = 0;
escapes = 0;
retval = kbinput;
}
break;
}
default:
/* Reset the escape counter. */
escapes = 0;
if (ascii_digits == 0)
/* Two escapes followed by a non-digit
* or a digit that would create an ASCII
* digit sequence greater than 2XX, and
* we're not in the middle of an ASCII
* character sequence: control character
* sequence mode. Interpret the control
* sequence and save the corresponding
* control character as the result. */
retval = get_control_kbinput(kbinput);
else {
/* If we were in the middle of an ASCII
* character sequence, reset the ASCII
* digit counter and save the character
* we got as the result. */
ascii_digits = 0;
retval = kbinput;
}
}
}
} }
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "get_accepted_kbinput(): kbinput = %d, meta_key = %d\n", kbinput, *meta_key); fprintf(stderr, "get_translated_kbinput(): kbinput = %d, es = %d, escapes = %d, ascii_digits = %d, retval = %d\n", kbinput, *es, escapes, ascii_digits, retval);
#endif #endif
return kbinput;
/* Return the result. */
return retval;
} }
/* Translate a three-digit decimal ASCII code from 000-255 into the /* Translate an ASCII character sequence: turn a three-digit decimal
* corresponding ASCII character. */ * ASCII code from 000-255 into its corresponding ASCII character. */
int get_ascii_kbinput(WINDOW *win, int kbinput) int get_ascii_kbinput(int kbinput, size_t ascii_digits
#ifndef NANO_SMALL
, int reset
#endif
)
{ {
int retval; static int ascii_kbinput = 0;
int retval = ERR;
switch (kbinput) { #ifndef NANO_SMALL
case '0': if (reset) {
case '1': ascii_kbinput = 0;
case '2': return ERR;
retval = (kbinput - '0') * 100;
break;
default:
return kbinput;
} }
#endif
kbinput = wgetch(win); switch (ascii_digits) {
switch (kbinput) { case 1:
case '0': /* Read in the first of the three ASCII digits. */
case '1': switch (kbinput) {
case '2': /* Add the digit we got to the 100's position of the
case '3': * ASCII character sequence holder. */
case '4': case '0':
case '5': case '1':
retval += (kbinput - '0') * 10; case '2':
ascii_kbinput += (kbinput - '0') * 100;
break;
default:
retval = kbinput;
}
break; break;
case '6': case 2:
case '7': /* Read in the second of the three ASCII digits. */
case '8': switch (kbinput) {
case '9': /* Add the digit we got to the 10's position of the
if (retval < 200) { * ASCII character sequence holder. */
retval += (kbinput - '0') * 10; case '0':
break; case '1':
case '2':
case '3':
case '4':
case '5':
ascii_kbinput += (kbinput - '0') * 10;
break;
case '6':
case '7':
case '8':
case '9':
if (ascii_kbinput < 200) {
ascii_kbinput += (kbinput - '0') * 10;
break;
}
default:
retval = kbinput;
} }
default:
return kbinput;
}
kbinput = wgetch(win);
switch (kbinput) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
retval += kbinput - '0';
break; break;
case '6': case 3:
case '7': /* Read in the third of the three ASCII digits. */
case '8': switch (kbinput) {
case '9': /* Add the digit we got to the 1's position of the ASCII
if (retval < 250) { * character sequence holder, and save the corresponding
retval += kbinput - '0'; * ASCII character as the result. */
break; case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
ascii_kbinput += (kbinput - '0');
retval = ascii_kbinput;
break;
case '6':
case '7':
case '8':
case '9':
if (ascii_kbinput < 250) {
ascii_kbinput += (kbinput - '0');
retval = ascii_kbinput;
break;
}
default:
retval = kbinput;
} }
default: break;
return kbinput;
} }
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "get_ascii_kbinput(): kbinput = %d\n", kbinput); fprintf(stderr, "get_ascii_kbinput(): kbinput = %d, ascii_digits = %d, ascii_kbinput = %d, retval = %d\n", kbinput, ascii_digits, ascii_kbinput, retval);
#endif
/* If the result is an ASCII character, reset the ASCII character
* sequence holder. */
if (retval != ERR)
ascii_kbinput = 0;
return retval;
}
/* Translate a control character sequence: turn an ASCII non-control
* character into its corresponding control character. */
int get_control_kbinput(int kbinput)
{
int retval = ERR;
/* We don't handle Ctrl-2 here, since Esc Esc 2 could be the first
* part of an ASCII character sequence. */
/* Ctrl-2 (Ctrl-Space) == Ctrl-@ == Ctrl-` */
if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
retval = NANO_CONTROL_SPACE;
/* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
else if (kbinput >= '3' && kbinput <= '7')
retval = kbinput - 24;
/* Ctrl-8 (Ctrl-?) */
else if (kbinput == '8' || kbinput == '?')
retval = NANO_CONTROL_8;
/* Ctrl-A to Ctrl-_ */
else if (kbinput >= 'A' && kbinput <= '_')
retval = kbinput - 64;
/* Ctrl-a to Ctrl-~ */
else if (kbinput >= 'a' && kbinput <= '~')
retval = kbinput - 96;
else
retval = kbinput;
#ifdef DEBUG
fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, ascii_digits, *complete, retval);
#endif #endif
return retval; return retval;
} }
/* Translate escape sequences, most of which correspond to extended /* Translate escape sequences, most of which correspond to extended
* keypad values. These sequences are generated when the terminal * keypad values, nto their corresponding key values. These sequences
* doesn't support the needed keys. Assume that Escape has already been * are generated when the keypad doesn't support the needed keys.
* read in, and that nodelay(win) is TRUE. */ * Assume that Escape has already been read in. */
int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t int get_escape_seq_kbinput(int *escape_seq, size_t es_len)
escape_seq_len)
{ {
int kbinput = ERR; int retval = ERR;
if (escape_seq_len > 1) { if (es_len > 1) {
switch (escape_seq[0]) { switch (escape_seq[0]) {
case 'O': case 'O':
switch (escape_seq[1]) { switch (escape_seq[1]) {
case '2': case '2':
if (escape_seq_len >= 3) { if (es_len >= 3) {
switch (escape_seq[2]) { switch (escape_seq[2]) {
case 'P': /* Esc O 2 P == F13 on case 'P': /* Esc O 2 P == F13 on
* xterm. */ * xterm. */
kbinput = KEY_F(13); retval = KEY_F(13);
break; break;
case 'Q': /* Esc O 2 Q == F14 on case 'Q': /* Esc O 2 Q == F14 on
* xterm. */ * xterm. */
kbinput = KEY_F(14); retval = KEY_F(14);
break; break;
} }
} }
...@@ -450,142 +571,142 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -450,142 +571,142 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
* VT100/VT320/xterm. */ * VT100/VT320/xterm. */
case 'D': /* Esc O D == Left on case 'D': /* Esc O D == Left on
* VT100/VT320/xterm. */ * VT100/VT320/xterm. */
kbinput = get_escape_seq_abcd(escape_seq[1]); retval = get_escape_seq_abcd(escape_seq[1]);
break; break;
case 'E': /* Esc O E == Center (5) on numeric keypad case 'E': /* Esc O E == Center (5) on numeric keypad
* with NumLock off on xterm. */ * with NumLock off on xterm. */
kbinput = '5'; retval = ERR;
break; break;
case 'F': /* Esc O F == End on xterm. */ case 'F': /* Esc O F == End on xterm. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case 'H': /* Esc O H == Home on xterm. */ case 'H': /* Esc O H == Home on xterm. */
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
case 'M': /* Esc O M == Enter on numeric keypad with case 'M': /* Esc O M == Enter on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/Eterm. */ * VT100/VT220/VT320/xterm/Eterm. */
kbinput = NANO_ENTER_KEY; retval = NANO_ENTER_KEY;
break; break;
case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Hurd case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Hurd
* console. */ * console. */
kbinput = KEY_F(1); retval = KEY_F(1);
break; break;
case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Hurd case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Hurd
* console. */ * console. */
kbinput = KEY_F(2); retval = KEY_F(2);
break; break;
case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Hurd case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Hurd
* console. */ * console. */
kbinput = KEY_F(3); retval = KEY_F(3);
break; break;
case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Hurd case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Hurd
* console. */ * console. */
kbinput = KEY_F(4); retval = KEY_F(4);
break; break;
case 'T': /* Esc O T == F5 on Hurd console. */ case 'T': /* Esc O T == F5 on Hurd console. */
kbinput = KEY_F(5); retval = KEY_F(5);
break; break;
case 'U': /* Esc O U == F6 on Hurd console. */ case 'U': /* Esc O U == F6 on Hurd console. */
kbinput = KEY_F(6); retval = KEY_F(6);
break; break;
case 'V': /* Esc O V == F7 on Hurd console. */ case 'V': /* Esc O V == F7 on Hurd console. */
kbinput = KEY_F(7); retval = KEY_F(7);
break; break;
case 'W': /* Esc O W == F8 on Hurd console. */ case 'W': /* Esc O W == F8 on Hurd console. */
kbinput = KEY_F(8); retval = KEY_F(8);
break; break;
case 'X': /* Esc O X == F9 on Hurd console. */ case 'X': /* Esc O X == F9 on Hurd console. */
kbinput = KEY_F(9); retval = KEY_F(9);
break; break;
case 'Y': /* Esc O Y == F10 on Hurd console. */ case 'Y': /* Esc O Y == F10 on Hurd console. */
kbinput = KEY_F(10); retval = KEY_F(10);
break; break;
case 'a': /* Esc O a == Ctrl-Up on rxvt. */ case 'a': /* Esc O a == Ctrl-Up on rxvt. */
case 'b': /* Esc O b == Ctrl-Down on rxvt. */ case 'b': /* Esc O b == Ctrl-Down on rxvt. */
case 'c': /* Esc O c == Ctrl-Right on rxvt. */ case 'c': /* Esc O c == Ctrl-Right on rxvt. */
case 'd': /* Esc O d == Ctrl-Left on rxvt. */ case 'd': /* Esc O d == Ctrl-Left on rxvt. */
kbinput = get_escape_seq_abcd(escape_seq[1]); retval = get_escape_seq_abcd(escape_seq[1]);
break; break;
case 'j': /* Esc O j == '*' on numeric keypad with case 'j': /* Esc O j == '*' on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = '*'; retval = '*';
break; break;
case 'k': /* Esc O k == '+' on numeric keypad with case 'k': /* Esc O k == '+' on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = '+'; retval = '+';
break; break;
case 'l': /* Esc O l == ',' on numeric keypad with case 'l': /* Esc O l == ',' on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = '+'; retval = '+';
break; break;
case 'm': /* Esc O m == '-' on numeric keypad with case 'm': /* Esc O m == '-' on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = '-'; retval = '-';
break; break;
case 'n': /* Esc O n == Delete (.) on numeric keypad case 'n': /* Esc O n == Delete (.) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = NANO_DELETE_KEY; retval = NANO_DELETE_KEY;
break; break;
case 'o': /* Esc O o == '/' on numeric keypad with case 'o': /* Esc O o == '/' on numeric keypad with
* NumLock off on * NumLock off on
* VT100/VT220/VT320/xterm/rxvt. */ * VT100/VT220/VT320/xterm/rxvt. */
kbinput = '/'; retval = '/';
break; break;
case 'p': /* Esc O p == Insert (0) on numeric keypad case 'p': /* Esc O p == Insert (0) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_INSERTFILE_KEY; retval = NANO_INSERTFILE_KEY;
break; break;
case 'q': /* Esc O q == End (1) on numeric keypad case 'q': /* Esc O q == End (1) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case 'r': /* Esc O r == Down (2) on numeric keypad case 'r': /* Esc O r == Down (2) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_NEXTLINE_KEY; retval = NANO_NEXTLINE_KEY;
break; break;
case 's': /* Esc O s == PageDown (3) on numeric case 's': /* Esc O s == PageDown (3) on numeric
* keypad with NumLock off on * keypad with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_NEXTPAGE_KEY; retval = NANO_NEXTPAGE_KEY;
break; break;
case 't': /* Esc O t == Left (4) on numeric keypad case 't': /* Esc O t == Left (4) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_BACK_KEY; retval = NANO_BACK_KEY;
break; break;
case 'u': /* Esc O u == Center (5) on numeric keypad case 'u': /* Esc O u == Center (5) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt/Eterm. */ * VT100/VT220/VT320/rxvt/Eterm. */
kbinput = '5'; retval = ERR;
break; break;
case 'v': /* Esc O v == Right (6) on numeric keypad case 'v': /* Esc O v == Right (6) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_FORWARD_KEY; retval = NANO_FORWARD_KEY;
break; break;
case 'w': /* Esc O w == Home (7) on numeric keypad case 'w': /* Esc O w == Home (7) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
case 'x': /* Esc O x == Up (8) on numeric keypad case 'x': /* Esc O x == Up (8) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_PREVLINE_KEY; retval = NANO_PREVLINE_KEY;
break; break;
case 'y': /* Esc O y == PageUp (9) on numeric keypad case 'y': /* Esc O y == PageUp (9) on numeric keypad
* with NumLock off on * with NumLock off on
* VT100/VT220/VT320/rxvt. */ * VT100/VT220/VT320/rxvt. */
kbinput = NANO_PREVPAGE_KEY; retval = NANO_PREVPAGE_KEY;
break; break;
} }
break; break;
...@@ -595,55 +716,55 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -595,55 +716,55 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
case 'b': /* Esc o b == Ctrl-Down on Eterm. */ case 'b': /* Esc o b == Ctrl-Down on Eterm. */
case 'c': /* Esc o c == Ctrl-Right on Eterm. */ case 'c': /* Esc o c == Ctrl-Right on Eterm. */
case 'd': /* Esc o d == Ctrl-Left on Eterm. */ case 'd': /* Esc o d == Ctrl-Left on Eterm. */
kbinput = get_escape_seq_abcd(escape_seq[1]); retval = get_escape_seq_abcd(escape_seq[1]);
break; break;
} }
break; break;
case '[': case '[':
switch (escape_seq[1]) { switch (escape_seq[1]) {
case '1': case '1':
if (escape_seq_len >= 3) { if (es_len >= 3) {
switch (escape_seq[2]) { switch (escape_seq[2]) {
case '1': /* Esc [ 1 1 ~ == F1 on case '1': /* Esc [ 1 1 ~ == F1 on
* rxvt/Eterm. */ * rxvt/Eterm. */
kbinput = KEY_F(1); retval = KEY_F(1);
break; break;
case '2': /* Esc [ 1 2 ~ == F2 on case '2': /* Esc [ 1 2 ~ == F2 on
* rxvt/Eterm. */ * rxvt/Eterm. */
kbinput = KEY_F(2); retval = KEY_F(2);
break; break;
case '3': /* Esc [ 1 3 ~ == F3 on case '3': /* Esc [ 1 3 ~ == F3 on
* rxvt/Eterm. */ * rxvt/Eterm. */
kbinput = KEY_F(3); retval = KEY_F(3);
break; break;
case '4': /* Esc [ 1 4 ~ == F4 on case '4': /* Esc [ 1 4 ~ == F4 on
* rxvt/Eterm. */ * rxvt/Eterm. */
kbinput = KEY_F(4); retval = KEY_F(4);
break; break;
case '5': /* Esc [ 1 5 ~ == F5 on case '5': /* Esc [ 1 5 ~ == F5 on
* xterm/rxvt/Eterm. */ * xterm/rxvt/Eterm. */
kbinput = KEY_F(5); retval = KEY_F(5);
break; break;
case '7': /* Esc [ 1 7 ~ == F6 on case '7': /* Esc [ 1 7 ~ == F6 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(6); retval = KEY_F(6);
break; break;
case '8': /* Esc [ 1 8 ~ == F7 on case '8': /* Esc [ 1 8 ~ == F7 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(7); retval = KEY_F(7);
break; break;
case '9': /* Esc [ 1 9 ~ == F8 on case '9': /* Esc [ 1 9 ~ == F8 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(8); retval = KEY_F(8);
break; break;
case ';': case ';':
if (escape_seq_len >= 4) { if (es_len >= 4) {
switch (escape_seq[3]) { switch (escape_seq[3]) {
case '2': case '2':
if (escape_seq_len >= 5) { if (es_len >= 5) {
switch (escape_seq[4]) { switch (escape_seq[4]) {
case 'A': /* Esc [ 1 ; 2 A == Shift-Up on case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
* xterm. */ * xterm. */
...@@ -653,13 +774,13 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -653,13 +774,13 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
* xterm. */ * xterm. */
case 'D': /* Esc [ 1 ; 2 D == Shift-Left on case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
* xterm. */ * xterm. */
kbinput = get_escape_seq_abcd(escape_seq[4]); retval = get_escape_seq_abcd(escape_seq[4]);
break; break;
} }
} }
break; break;
case '5': case '5':
if (escape_seq_len >= 5) { if (es_len >= 5) {
switch (escape_seq[4]) { switch (escape_seq[4]) {
case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
* xterm. */ * xterm. */
...@@ -669,7 +790,7 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -669,7 +790,7 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
* xterm. */ * xterm. */
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
* xterm. */ * xterm. */
kbinput = get_escape_seq_abcd(escape_seq[4]); retval = get_escape_seq_abcd(escape_seq[4]);
break; break;
} }
} }
...@@ -679,81 +800,81 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -679,81 +800,81 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
break; break;
default: /* Esc [ 1 ~ == Home on default: /* Esc [ 1 ~ == Home on
* VT320/Linux console. */ * VT320/Linux console. */
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
} }
} }
break; break;
case '2': case '2':
if (escape_seq_len >= 3) { if (es_len >= 3) {
switch (escape_seq[2]) { switch (escape_seq[2]) {
case '0': /* Esc [ 2 0 ~ == F9 on case '0': /* Esc [ 2 0 ~ == F9 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(9); retval = KEY_F(9);
break; break;
case '1': /* Esc [ 2 1 ~ == F10 on case '1': /* Esc [ 2 1 ~ == F10 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(10); retval = KEY_F(10);
break; break;
case '3': /* Esc [ 2 3 ~ == F11 on case '3': /* Esc [ 2 3 ~ == F11 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(11); retval = KEY_F(11);
break; break;
case '4': /* Esc [ 2 4 ~ == F12 on case '4': /* Esc [ 2 4 ~ == F12 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm/rxvt/Eterm. */ * console/xterm/rxvt/Eterm. */
kbinput = KEY_F(12); retval = KEY_F(12);
break; break;
case '5': /* Esc [ 2 5 ~ == F13 on case '5': /* Esc [ 2 5 ~ == F13 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/rxvt/Eterm. */ * console/rxvt/Eterm. */
kbinput = KEY_F(13); retval = KEY_F(13);
break; break;
case '6': /* Esc [ 2 6 ~ == F14 on case '6': /* Esc [ 2 6 ~ == F14 on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/rxvt/Eterm. */ * console/rxvt/Eterm. */
kbinput = KEY_F(14); retval = KEY_F(14);
break; break;
default: /* Esc [ 2 ~ == Insert on default: /* Esc [ 2 ~ == Insert on
* VT220/VT320/Linux * VT220/VT320/Linux
* console/xterm. */ * console/xterm. */
kbinput = NANO_INSERTFILE_KEY; retval = NANO_INSERTFILE_KEY;
break; break;
} }
} }
break; break;
case '3': /* Esc [ 3 ~ == Delete on case '3': /* Esc [ 3 ~ == Delete on
* VT220/VT320/Linux console/xterm. */ * VT220/VT320/Linux console/xterm. */
kbinput = NANO_DELETE_KEY; retval = NANO_DELETE_KEY;
break; break;
case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
* console/xterm. */ * console/xterm. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case '5': /* Esc [ 5 ~ == PageUp on case '5': /* Esc [ 5 ~ == PageUp on
* VT220/VT320/Linux console/xterm; Esc [ * VT220/VT320/Linux console/xterm; Esc [
* 5 ^ == PageUp on Eterm. */ * 5 ^ == PageUp on Eterm. */
kbinput = NANO_PREVPAGE_KEY; retval = NANO_PREVPAGE_KEY;
break; break;
case '6': /* Esc [ 6 ~ == PageDown on case '6': /* Esc [ 6 ~ == PageDown on
* VT220/VT320/Linux console/xterm; Esc [ * VT220/VT320/Linux console/xterm; Esc [
* 6 ^ == PageDown on Eterm. */ * 6 ^ == PageDown on Eterm. */
kbinput = NANO_NEXTPAGE_KEY; retval = NANO_NEXTPAGE_KEY;
break; break;
case '7': /* Esc [ 7 ~ == Home on rxvt. */ case '7': /* Esc [ 7 ~ == Home on rxvt. */
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
case '8': /* Esc [ 8 ~ == End on rxvt. */ case '8': /* Esc [ 8 ~ == End on rxvt. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case '9': /* Esc [ 9 == Delete on Hurd console. */ case '9': /* Esc [ 9 == Delete on Hurd console. */
kbinput = NANO_DELETE_KEY; retval = NANO_DELETE_KEY;
break; break;
case '@': /* Esc [ @ == Insert on Hurd console. */ case '@': /* Esc [ @ == Insert on Hurd console. */
kbinput = NANO_INSERTFILE_KEY; retval = NANO_INSERTFILE_KEY;
break; break;
case 'A': /* Esc [ A == Up on ANSI/VT220/Linux case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
* console/FreeBSD console/Hurd * console/FreeBSD console/Hurd
...@@ -767,126 +888,126 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -767,126 +888,126 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
case 'D': /* Esc [ D == Left on ANSI/VT220/Linux case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
* console/FreeBSD console/Hurd * console/FreeBSD console/Hurd
* console/rxvt/Eterm. */ * console/rxvt/Eterm. */
kbinput = get_escape_seq_abcd(escape_seq[1]); retval = get_escape_seq_abcd(escape_seq[1]);
break; break;
case 'E': /* Esc [ E == Center (5) on numeric keypad case 'E': /* Esc [ E == Center (5) on numeric keypad
* with NumLock off on FreeBSD console. */ * with NumLock off on FreeBSD console. */
kbinput = '5'; retval = ERR;
break; break;
case 'F': /* Esc [ F == End on FreeBSD case 'F': /* Esc [ F == End on FreeBSD
* console/Eterm. */ * console/Eterm. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case 'G': /* Esc [ G == PageDown on FreeBSD case 'G': /* Esc [ G == PageDown on FreeBSD
* console. */ * console. */
kbinput = NANO_NEXTPAGE_KEY; retval = NANO_NEXTPAGE_KEY;
break; break;
case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
* console/Hurd console/Eterm. */ * console/Hurd console/Eterm. */
kbinput = NANO_HOME_KEY; retval = NANO_HOME_KEY;
break; break;
case 'I': /* Esc [ I == PageUp on FreeBSD case 'I': /* Esc [ I == PageUp on FreeBSD
* console. */ * console. */
kbinput = NANO_PREVPAGE_KEY; retval = NANO_PREVPAGE_KEY;
break; break;
case 'L': /* Esc [ L == Insert on ANSI/FreeBSD case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
* console. */ * console. */
kbinput = NANO_INSERTFILE_KEY; retval = NANO_INSERTFILE_KEY;
break; break;
case 'M': /* Esc [ M == F1 on FreeBSD console. */ case 'M': /* Esc [ M == F1 on FreeBSD console. */
kbinput = KEY_F(1); retval = KEY_F(1);
break; break;
case 'N': /* Esc [ N == F2 on FreeBSD console. */ case 'N': /* Esc [ N == F2 on FreeBSD console. */
kbinput = KEY_F(2); retval = KEY_F(2);
break; break;
case 'O': case 'O':
if (escape_seq_len >= 3) { if (es_len >= 3) {
switch (escape_seq[2]) { switch (escape_seq[2]) {
case 'P': /* Esc [ O P == F1 on case 'P': /* Esc [ O P == F1 on
* xterm. */ * xterm. */
kbinput = KEY_F(1); retval = KEY_F(1);
break; break;
case 'Q': /* Esc [ O Q == F2 on case 'Q': /* Esc [ O Q == F2 on
* xterm. */ * xterm. */
kbinput = KEY_F(2); retval = KEY_F(2);
break; break;
case 'R': /* Esc [ O R == F3 on case 'R': /* Esc [ O R == F3 on
* xterm. */ * xterm. */
kbinput = KEY_F(3); retval = KEY_F(3);
break; break;
case 'S': /* Esc [ O S == F4 on case 'S': /* Esc [ O S == F4 on
* xterm. */ * xterm. */
kbinput = KEY_F(4); retval = KEY_F(4);
break; break;
default: /* Esc [ O == F3 on default: /* Esc [ O == F3 on
* FreeBSD console. */ * FreeBSD console. */
kbinput = KEY_F(3); retval = KEY_F(3);
break; break;
} }
} }
break; break;
case 'P': /* Esc [ P == F4 on FreeBSD console. */ case 'P': /* Esc [ P == F4 on FreeBSD console. */
kbinput = KEY_F(4); retval = KEY_F(4);
break; break;
case 'Q': /* Esc [ Q == F5 on FreeBSD console. */ case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
kbinput = KEY_F(5); retval = KEY_F(5);
break; break;
case 'R': /* Esc [ R == F6 on FreeBSD console. */ case 'R': /* Esc [ R == F6 on FreeBSD console. */
kbinput = KEY_F(6); retval = KEY_F(6);
break; break;
case 'S': /* Esc [ S == F7 on FreeBSD console. */ case 'S': /* Esc [ S == F7 on FreeBSD console. */
kbinput = KEY_F(7); retval = KEY_F(7);
break; break;
case 'T': /* Esc [ T == F8 on FreeBSD console. */ case 'T': /* Esc [ T == F8 on FreeBSD console. */
kbinput = KEY_F(8); retval = KEY_F(8);
break; break;
case 'U': /* Esc [ U == PageDown on Hurd console. */ case 'U': /* Esc [ U == PageDown on Hurd console. */
kbinput = NANO_NEXTPAGE_KEY; retval = NANO_NEXTPAGE_KEY;
break; break;
case 'V': /* Esc [ V == PageUp on Hurd console. */ case 'V': /* Esc [ V == PageUp on Hurd console. */
kbinput = NANO_PREVPAGE_KEY; retval = NANO_PREVPAGE_KEY;
break; break;
case 'W': /* Esc [ W == F11 on FreeBSD console. */ case 'W': /* Esc [ W == F11 on FreeBSD console. */
kbinput = KEY_F(11); retval = KEY_F(11);
break; break;
case 'X': /* Esc [ X == F12 on FreeBSD console. */ case 'X': /* Esc [ X == F12 on FreeBSD console. */
kbinput = KEY_F(12); retval = KEY_F(12);
break; break;
case 'Y': /* Esc [ Y == End on Hurd console. */ case 'Y': /* Esc [ Y == End on Hurd console. */
kbinput = NANO_END_KEY; retval = NANO_END_KEY;
break; break;
case 'Z': /* Esc [ Z == F14 on FreeBSD console. */ case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
kbinput = KEY_F(14); retval = KEY_F(14);
break; break;
case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */ case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */ case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
case 'c': /* Esc [ c == Shift-Right on case 'c': /* Esc [ c == Shift-Right on
* rxvt/Eterm. */ * rxvt/Eterm. */
case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */ case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
kbinput = get_escape_seq_abcd(escape_seq[1]); retval = get_escape_seq_abcd(escape_seq[1]);
break; break;
case '[': case '[':
if (escape_seq_len >= 3) { if (es_len >= 3) {
switch (escape_seq[2]) { switch (escape_seq[2]) {
case 'A': /* Esc [ [ A == F1 on Linux case 'A': /* Esc [ [ A == F1 on Linux
* console. */ * console. */
kbinput = KEY_F(1); retval = KEY_F(1);
break; break;
case 'B': /* Esc [ [ B == F2 on Linux case 'B': /* Esc [ [ B == F2 on Linux
* console. */ * console. */
kbinput = KEY_F(2); retval = KEY_F(2);
break; break;
case 'C': /* Esc [ [ C == F3 on Linux case 'C': /* Esc [ [ C == F3 on Linux
* console. */ * console. */
kbinput = KEY_F(3); retval = KEY_F(3);
break; break;
case 'D': /* Esc [ [ D == F4 on Linux case 'D': /* Esc [ [ D == F4 on Linux
* console. */ * console. */
kbinput = KEY_F(4); retval = KEY_F(4);
break; break;
case 'E': /* Esc [ [ E == F5 on Linux case 'E': /* Esc [ [ E == F5 on Linux
* console. */ * console. */
kbinput = KEY_F(5); retval = KEY_F(5);
break; break;
} }
} }
...@@ -896,14 +1017,11 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t ...@@ -896,14 +1017,11 @@ int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
} }
} }
if (kbinput == ERR) { #ifdef DEBUG
/* This escape sequence is unrecognized; send it back. */ fprintf(stderr, "get_escape_seq_kbinput(): retval = %d\n", retval);
for (; escape_seq_len > 1; escape_seq_len--) #endif
ungetch(escape_seq[escape_seq_len - 1]);
kbinput = escape_seq[0];
}
return kbinput; return retval;
} }
/* Return the equivalent arrow key value for the case-insensitive /* Return the equivalent arrow key value for the case-insensitive
...@@ -925,6 +1043,176 @@ int get_escape_seq_abcd(int kbinput) ...@@ -925,6 +1043,176 @@ int get_escape_seq_abcd(int kbinput)
} }
} }
/* Read in a string of input characters (e.g. an escape sequence)
* verbatim. Store the string in v_kbinput and return the length
* of the string in v_len. Assume nodelay(win) is FALSE. */
int *get_verbatim_kbinput(WINDOW *win, int *v_kbinput, size_t
*v_len, int allow_ascii)
{
int kbinput;
size_t i = 0, v_newlen = 0;
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
#endif
*v_len = 0;
v_kbinput = (int *)nmalloc(sizeof(int));
/* Turn off flow control characters if necessary so that we can type
* them in verbatim, and turn the keypad off so that we don't get
* extended keypad values outside the ASCII range. */
if (ISSET(PRESERVE))
disable_flow_control();
keypad(win, FALSE);
/* Read the first character using blocking input, since using
* non-blocking input will eat up all unused CPU. Then increment
* v_len and save the character in v_kbinput. */
kbinput = wgetch(win);
(*v_len)++;
v_kbinput[0] = kbinput;
#ifdef DEBUG
fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %d\n", kbinput, *v_len);
#endif
/* Read any following characters using non-blocking input, until
* there aren't any left to be read, and save the complete string of
* characters in v_kbinput, incrementing v_len accordingly. We read
* them all at once in order to minimize the chance that there might
* be a delay greater than nodelay() provides for between them, in
* which case we'll stop before all of them are read. */
nodelay(win, TRUE);
while ((kbinput = wgetch(win)) != ERR) {
(*v_len)++;
v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
v_kbinput[*v_len - 1] = kbinput;
#ifdef DEBUG
fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %d\n", kbinput, *v_len);
#endif
}
nodelay(win, FALSE);
/* Pass the string of characters to get_untranslated_kbinput(), one
* by one, so it can handle them as ASCII character sequences and/or
* escape sequences. Filter out ERR's from v_kbinput in the
* process; they shouldn't occur in the string of characters unless
* we're reading an incomplete sequence, in which case we only want
* to keep the complete sequence. */
for (; i < *v_len; i++) {
v_kbinput[v_newlen] = get_untranslated_kbinput(v_kbinput[i], i,
allow_ascii
#ifndef NANO_SMALL
, FALSE
#endif
);
if (v_kbinput[i] != ERR && v_kbinput[v_newlen] != ERR)
v_newlen++;
}
if (v_newlen == 0) {
/* If there were no characters after the ERR's were filtered
* out, set v_len and reallocate v_kbinput to account for
* one character, and set that character to ERR. */
*v_len = 1;
v_kbinput = (int *)nrealloc(v_kbinput, sizeof(int));
v_kbinput[0] = ERR;
} else if (v_newlen != *v_len) {
/* If there were fewer characters after the ERR's were filtered
* out, set v_len and reallocate v_kbinput to account for
* the new number of characters. */
*v_len = v_newlen;
v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
}
/* If allow_ascii is TRUE and v_kbinput[0] is ERR, we need to
* complete an ASCII character sequence. Keep reading in characters
* using blocking input until we get a complete sequence. */
if (allow_ascii && v_kbinput[0] == ERR) {
while (v_kbinput[0] == ERR) {
kbinput = wgetch(win);
v_kbinput[0] = get_untranslated_kbinput(kbinput, i,
allow_ascii
#ifndef NANO_SMALL
, FALSE
#endif
);
i++;
}
}
/* Turn flow control characters back on if necessary and turn the
* keypad back on now that we're done. */
if (ISSET(PRESERVE))
enable_flow_control();
keypad(win, TRUE);
#ifndef NANO_SMALL
allow_pending_sigwinch(FALSE);
#endif
return v_kbinput;
}
int get_untranslated_kbinput(int kbinput, size_t position, int
allow_ascii
#ifndef NANO_SMALL
, int reset
#endif
)
{
static size_t ascii_digits = 0;
int retval;
#ifndef NANO_SMALL
if (reset) {
ascii_digits = 0;
return ERR;
}
#endif
if (allow_ascii) {
/* position is equal to the number of ASCII digits we've read so
* far, and kbinput is a digit from '0' to '9': ASCII character
* sequence mode. If the digit sequence's range is limited to
* 2XX (the first digit is in the '0' to '2' range and it's the
* first digit, or if it's in the full digit range and it's not
* the first digit), increment the ASCII digit counter and
* interpret the digit. If the digit sequence's range is not
* limited to 2XX, fall through. */
if (position == ascii_digits && kbinput >= '0' && kbinput <= '9') {
if (kbinput <= '2' || ascii_digits > 0) {
ascii_digits++;
kbinput = get_ascii_kbinput(kbinput, ascii_digits
#ifndef NANO_SMALL
, FALSE
#endif
);
if (kbinput != ERR)
/* If we've read in a complete ASCII digit sequence,
* reset the ASCII digit counter. */
ascii_digits = 0;
}
} else if (ascii_digits > 0)
/* position is not equal to the number of ASCII digits we've
* read or kbinput is a non-digit, and we're in the middle
* of an ASCII character sequence. Reset the ASCII digit
* counter. */
ascii_digits = 0;
}
/* Save the corresponding ASCII character as the result if we've
* read in a complete ASCII digit sequence, or the passed-in
* character if we haven't. */
retval = kbinput;
#ifdef DEBUG
fprintf(stderr, "get_untranslated_kbinput(): kbinput = %d, position = %d, ascii_digits = %d\n", kbinput, position, ascii_digits);
#endif
return retval;
}
#ifndef DISABLE_MOUSE #ifndef DISABLE_MOUSE
/* Check for a mouse event, and if one's taken place, save the /* Check for a mouse event, and if one's taken place, save the
* coordinates where it took place in mouse_x and mouse_y. After that, * coordinates where it took place in mouse_x and mouse_y. After that,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment