From: David Lawrence Ramsey Date: Sun, 17 Aug 2003 02:48:43 +0000 (+0000) Subject: low-level input overhaul X-Git-Tag: v1.3.0~48 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=4d7c260270228d4496311d84a2bb73f725f22e8e;p=nano.git low-level input overhaul git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1523 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/ChangeLog b/ChangeLog index ee70774d..1cbd4832 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,36 @@ CVS code - - +- General: + - Complete overhaul and abstraction of the lowest level of + keyboard input, mostly rewritten but incorporating a few bits + from the old functions and adding support for Pico's Esc Esc + [three-digit decimal ASCII code] input method. New functions + get_kbinput(), get_verbatim_kbinput(), get_ignored_kbinput(), + get_accepted_kbinput(), get_ascii_kbinput(), + get_escape_seq_kbinput(), and get_skip_tilde_kbinput(). These + should work properly on FreeBSD (due to code and input + provided by Lee Nelson and Wouter van Hemel, respectively). + (DLR) + - The -K/--keypad command line/rcfile option has been removed, + and keypad() is now always TRUE. keypad_on() in winio.c and + the check for _use_keypad in configure.ac have both been + removed. (DLR) + - The -d/--rebinddelete command line/rcfile option, equivalent + to Pico's -d, has been added. It is intended to work around + the problem with Backspace/Delete confusion on some terminals, + notably FreeBSD; if your Backspace key acts like Delete, this + option will fix that. (DLR) +- files.c: + do_browser(): + - Some of the Pico compatibility options in the file browser + that don't work properly for Pico 4.6 have been removed. + Backspace, 'g', 'l', 'q', and 'u' are invalid, 'd' deletes the + highlighted file, and 'r' renames the highlighted file. (DLR) +- nano.h: + - Define KEY_SUSPEND as -1 when slang is used, as slang has no + KEY_SUSPEND equivalent. When nano is compiled with slang + support, pressing Ctrl-Z to suspend nano at the Linux console + with keypad(TRUE) generates Ctrl-Z instead of KEY_SUSPEND + (which is what ncurses generates then). (DLR) - AUTHORS - Updated to show 1.2/1.3 maintainers. diff --git a/configure.ac b/configure.ac index c7302cb3..da0ef414 100644 --- a/configure.ac +++ b/configure.ac @@ -330,20 +330,6 @@ AC_CHECK_LIB([$CURSES_LIB_NAME], use_default_colors, AC_DEFINE(HAVE_USE_DEFAULT_ if test x$slang_support != xyes; then AC_CHECK_LIB([$CURSES_LIB_NAME], wresize, AC_DEFINE(HAVE_WRESIZE, 1, [Define this if you have the wresize function in your ncurses-type library.])) AC_CHECK_LIB([$CURSES_LIB_NAME], resizeterm, AC_DEFINE(HAVE_RESIZETERM, 1, [Define this if you have the resizeterm function in your ncurses-type library.])) - - # Taken from aumix (can't tell from the variable name?) - AC_CACHE_CHECK([for private member _use_keypad in WINDOW], - aumix_cv_struct_window_usekeypad, - [AC_TRY_COMPILE([#ifdef HAVE_NCURSES_H -#include -#else -#include -#endif], [WINDOW w; w._use_keypad;], - aumix_cv_struct_window_usekeypad=yes, aumix_cv_struct_window_usekeypad=no)]) - - if test $aumix_cv_struct_window_usekeypad = yes; then - AC_DEFINE(HAVE_USEKEYPAD, 1, [Define this if your curses lib has the _use_keypad flag.]) - fi fi dnl Parse any configure options diff --git a/files.c b/files.c index b70ed946..4193a932 100644 --- a/files.c +++ b/files.c @@ -2477,9 +2477,9 @@ char *do_browser(const char *inpath) struct stat st; char *foo, *retval = NULL; static char *path = NULL; - int numents = 0, i = 0, j = 0, kbinput = 0, longest = 0, abort = 0; - int col = 0, selected = 0, editline = 0, width = 0, filecols = 0; - int lineno = 0, kb; + int numents = 0, i = 0, j = 0, kbinput = -1, meta, longest = 0; + int abort = 0, col = 0, selected = 0, editline = 0, width = 0; + int filecols = 0, lineno = 0; char **filelist = (char **)NULL; #if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION) MEVENT mevent; @@ -2505,7 +2505,6 @@ char *do_browser(const char *inpath) /* Sort the list by directory first, then alphabetically */ qsort(filelist, numents, sizeof(char *), diralphasort); - kb = keypad_on(edit, 1); titlebar(path); bottombars(browser_list); curs_set(0); @@ -2569,34 +2568,23 @@ char *do_browser(const char *inpath) break; #endif case NANO_UP_KEY: - case KEY_UP: - case 'u': if (selected - width >= 0) selected -= width; break; case NANO_BACK_KEY: - case KEY_LEFT: - case NANO_BACKSPACE_KEY: - case 127: - case 'l': if (selected > 0) selected--; break; - case KEY_DOWN: case NANO_DOWN_KEY: - case 'd': if (selected + width <= numents - 1) selected += width; break; - case KEY_RIGHT: case NANO_FORWARD_KEY: - case 'r': if (selected < numents - 1) selected++; break; case NANO_PREVPAGE_KEY: case NANO_PREVPAGE_FKEY: - case KEY_PPAGE: case '-': if (selected >= (editwinrows + lineno % editwinrows) * width) selected -= (editwinrows + lineno % editwinrows) * width; @@ -2605,7 +2593,6 @@ char *do_browser(const char *inpath) break; case NANO_NEXTPAGE_KEY: case NANO_NEXTPAGE_FKEY: - case KEY_NPAGE: case ' ': selected += (editwinrows - lineno % editwinrows) * width; if (selected >= numents) @@ -2615,7 +2602,6 @@ char *do_browser(const char *inpath) case NANO_HELP_FKEY: do_help(); break; - case KEY_ENTER: case NANO_ENTER_KEY: case 's': /* More Pico compatibility */ case 'S': @@ -2678,10 +2664,8 @@ char *do_browser(const char *inpath) return do_browser(path); /* Goto a specific directory */ - case 'g': /* Pico compatibility */ - case 'G': case NANO_GOTO_KEY: - + case NANO_GOTO_FKEY: curs_set(1); j = statusq(0, gotodir_list, "", #ifndef NANO_SMALL @@ -2726,11 +2710,10 @@ char *do_browser(const char *inpath) return do_browser(path); /* Stuff we want to abort the browser */ - case 'q': - case 'Q': case 'e': /* Pico compatibility, yeech */ case 'E': case NANO_CANCEL_KEY: + case NANO_EXIT_KEY: case NANO_EXIT_FKEY: abort = 1; break; @@ -2806,12 +2789,11 @@ char *do_browser(const char *inpath) } } wrefresh(edit); - } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY); + } while ((kbinput = get_kbinput(edit, &meta, ISSET(REBIND_DELETE))) != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY); curs_set(1); blank_edit(); titlebar(NULL); edit_refresh(); - kb = keypad_on(edit, kb); /* cleanup */ free_charptrarray(filelist, numents); diff --git a/nano.c b/nano.c index 1cb3aedc..c7bb5f52 100644 --- a/nano.c +++ b/nano.c @@ -66,9 +66,6 @@ static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */ /* What we do when we're all set to exit */ RETSIGTYPE finish(int sigage) { - keypad(edit, TRUE); - keypad(bottomwin, TRUE); - if (!ISSET(NO_HELP)) { mvwaddstr(bottomwin, 1, 0, hblank); mvwaddstr(bottomwin, 2, 0, hblank); @@ -251,9 +248,6 @@ void window_init(void) void mouse_init(void) { if (ISSET(USE_MOUSE)) { - keypad_on(edit, 1); - keypad_on(bottomwin, 1); - mousemask(BUTTON1_RELEASED, NULL); mouseinterval(50); } else @@ -639,7 +633,6 @@ void usage(void) print1opt("-H", "--historylog", _("Log & read search/replace string history")); print1opt("-I", "--ignorercfiles", _("Don't look at nanorc files")); #endif - print1opt("-K", "--keypad", _("Use alternate keypad routines")); #ifndef NANO_SMALL print1opt("-M", "--mac", _("Write file in Mac format")); print1opt("-N", "--noconvert", _("Don't convert files from DOS/Mac format")); @@ -660,6 +653,7 @@ void usage(void) #endif print1opt("-c", "--const", _("Constantly show cursor position")); #ifndef NANO_SMALL + print1opt("-d", "--rebinddelete", _("Fix Backspace if it acts like Delete")); print1opt("-i", "--autoindent", _("Automatically indent new lines")); print1opt("-k", "--cut", _("Let ^K cut from cursor to end of line")); #endif @@ -3001,6 +2995,7 @@ int main(int argc, char *argv[]) const shortcut *s; int keyhandled = 0; /* Have we handled the keystroke yet? */ int kbinput = -1; /* Input from keyboard */ + int meta; #ifndef NANO_SMALL const toggle *t; @@ -3019,7 +3014,6 @@ int main(int argc, char *argv[]) {"historylog", 0, 0, 'H'}, {"ignorercfiles", 0, 0, 'I'}, #endif - {"keypad", 0, 0, 'K'}, #ifndef DISABLE_JUSTIFY {"quotestr", 1, 0, 'Q'}, #endif @@ -3032,6 +3026,7 @@ int main(int argc, char *argv[]) {"syntax", 1, 0, 'Y'}, #endif {"const", 0, 0, 'c'}, + {"rebinddelete", 0, 0, 'd'}, {"nofollow", 0, 0, 'l'}, #if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION) {"mouse", 0, 0, 'm'}, @@ -3080,11 +3075,11 @@ int main(int argc, char *argv[]) #endif #ifdef HAVE_GETOPT_LONG - while ((optchr = getopt_long(argc, argv, "h?BDFHIKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz", + while ((optchr = getopt_long(argc, argv, "h?BDFHIMNQ:RST:VY:abcdefgijklmo:pr:s:tvwxz", long_options, &option_index)) != -1) { #else while ((optchr = - getopt(argc, argv, "h?BDFHIKMNQ:RST:VY:abcefgijklmo:pr:s:tvwxz")) != -1) { + getopt(argc, argv, "h?BDFHIMNQ:RST:VY:abcdefgijklmo:pr:s:tvwxz")) != -1) { #endif switch (optchr) { @@ -3118,9 +3113,6 @@ int main(int argc, char *argv[]) SET(NO_RCFILE); break; #endif - case 'K': - SET(ALT_KEYPAD); - break; #ifndef NANO_SMALL case 'M': SET(MAC_FILE); @@ -3173,6 +3165,9 @@ int main(int argc, char *argv[]) case 'c': SET(CONSTUPDATE); break; + case 'd': + SET(REBIND_DELETE); + break; #ifndef NANO_SMALL case 'i': SET(AUTOINDENT); @@ -3389,10 +3384,8 @@ int main(int argc, char *argv[]) mouse_init(); #endif - if (!ISSET(ALT_KEYPAD)) { - keypad(edit, TRUE); - keypad(bottomwin, TRUE); - } + keypad(edit, TRUE); + keypad(bottomwin, TRUE); #ifdef DEBUG fprintf(stderr, "Main: bottom win\n"); @@ -3456,160 +3449,12 @@ int main(int argc, char *argv[]) raw(); #endif - kbinput = wgetch(edit); + kbinput = get_kbinput(edit, &meta, ISSET(REBIND_DELETE)); #ifdef DEBUG fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput); #endif - if (kbinput == 27) { /* Grab Alt-key stuff first */ - kbinput = wgetch(edit); + if (meta == 1) { switch (kbinput) { - /* Alt-O, suddenly very important ;) */ - case 'O': - kbinput = wgetch(edit); - /* Shift or Ctrl + Arrows are Alt-O-[2,5,6]-[A,B,C,D] on some terms */ - if (kbinput == '2' || kbinput == '5' || kbinput == '6') - kbinput = wgetch(edit); - if ((kbinput <= 'D' && kbinput >= 'A') || - (kbinput <= 'd' && kbinput >= 'a')) - kbinput = abcd(kbinput); - else if (kbinput <= 'z' && kbinput >= 'j') - print_numlock_warning(); - else if (kbinput <= 'S' && kbinput >= 'P') - kbinput = KEY_F(kbinput - 79); -#ifdef DEBUG - else { - fprintf(stderr, "I got Alt-O-%c! (%d)\n", - kbinput, kbinput); - break; - } -#endif - break; - case 27: - /* If we get Alt-Alt, the next keystroke should be the same as a - control sequence */ - modify_control_seq = 1; - keyhandled = 1; - break; - case '[': - kbinput = wgetch(edit); - switch (kbinput) { - case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */ - kbinput = wgetch(edit); - if (kbinput >= '1' && kbinput <= '5') { - kbinput = KEY_F(kbinput - 48); - wgetch(edit); - } else if (kbinput >= '7' && kbinput <= '9') { - kbinput = KEY_F(kbinput - 49); - wgetch(edit); - } else if (kbinput == '~') - kbinput = KEY_HOME; -#ifdef DEBUG - else { - fprintf(stderr, "I got Alt-[-1-%c! (%d)\n", - kbinput, kbinput); - break; - } -#endif - break; - case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */ - kbinput = wgetch(edit); - switch (kbinput) { - case '0': - kbinput = KEY_F(9); - wgetch(edit); - break; - case '1': - kbinput = KEY_F(10); - wgetch(edit); - break; - case '3': - kbinput = KEY_F(11); - wgetch(edit); - break; - case '4': - kbinput = KEY_F(12); - wgetch(edit); - break; - case '~': - kbinput = NANO_INSERTFILE_KEY; - break; -#ifdef DEBUG - default: - fprintf(stderr, "I got Alt-[-2-%c! (%d)\n", - kbinput, kbinput); - break; -#endif - } - break; - case '3': /* Alt-[-3 = Delete? */ - kbinput = NANO_DELETE_KEY; - wgetch(edit); - break; - case '4': /* Alt-[-4 = End? */ - kbinput = NANO_END_KEY; - wgetch(edit); - break; - case '5': /* Alt-[-5 = Page Up */ - kbinput = KEY_PPAGE; - wgetch(edit); - break; - case 'V': /* Alt-[-V = Page Up in Hurd Console */ - case 'I': /* Alt-[-I = Page Up - FreeBSD Console */ - kbinput = KEY_PPAGE; - break; - case '6': /* Alt-[-6 = Page Down */ - kbinput = KEY_NPAGE; - wgetch(edit); - break; - case 'U': /* Alt-[-U = Page Down in Hurd Console */ - case 'G': /* Alt-[-G = Page Down - FreeBSD Console */ - kbinput = KEY_NPAGE; - break; - case '7': - kbinput = KEY_HOME; - wgetch(edit); - break; - case '8': - kbinput = KEY_END; - wgetch(edit); - break; - case '9': /* Alt-[-9 = Delete in Hurd Console */ - kbinput = KEY_DC; - break; - case '@': /* Alt-[-@ = Insert in Hurd Console */ - case 'L': /* Alt-[-L = Insert - FreeBSD Console */ - kbinput = NANO_INSERTFILE_KEY; - break; - case '[': /* Alt-[-[-[A-E], F1-F5 in Linux console */ - kbinput = wgetch(edit); - if (kbinput >= 'A' && kbinput <= 'E') - kbinput = KEY_F(kbinput - 64); - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'a': - case 'b': - case 'c': - case 'd': - kbinput = abcd(kbinput); - break; - case 'H': - kbinput = KEY_HOME; - break; - case 'F': - case 'Y': /* End Key in Hurd Console */ - kbinput = KEY_END; - break; - default: -#ifdef DEBUG - fprintf(stderr, "I got Alt-[-%c! (%d)\n", - kbinput, kbinput); -#endif - break; - } - break; #ifdef ENABLE_MULTIBUFFER case NANO_OPENPREV_KEY: case NANO_OPENPREV_ALTKEY: @@ -3656,23 +3501,6 @@ int main(int argc, char *argv[]) break; } } - /* Hack, make insert key do something useful, like insert file */ - else if (kbinput == KEY_IC) - kbinput = NANO_INSERTFILE_KEY; - - /* If modify_control_seq is set, we received an Alt-Alt - sequence before this, so we make this key a control sequence - by subtracting 32, 64, or 96, depending on its value. */ - if (!keyhandled && modify_control_seq) { - if (kbinput == ' ') - kbinput -= 32; - else if (kbinput >= 'A' && kbinput < 'a') - kbinput -= 64; - else if (kbinput >= 'a' && kbinput <= 'z') - kbinput -= 96; - - modify_control_seq = 0; - } /* Look through the main shortcut list to see if we've hit a shortcut key */ @@ -3707,19 +3535,18 @@ int main(int argc, char *argv[]) #ifdef _POSIX_VDISABLE /* Don't even think about changing this string */ - if (kbinput == 19) - statusbar(_("XOFF ignored, mumble mumble.")); - if (kbinput == 17) + if (kbinput == NANO_CONTROL_Q) statusbar(_("XON ignored, mumble mumble.")); + if (kbinput == NANO_CONTROL_S) + statusbar(_("XOFF ignored, mumble mumble.")); #endif /* If we're in raw mode or using Alt-Alt-x, we have to catch Control-S and Control-Q */ - if (kbinput == 17 || kbinput == 19) + if (kbinput == NANO_CONTROL_Q || kbinput == NANO_CONTROL_S) keyhandled = 1; - /* Catch ^Z by hand when triggered also - 407 == ^Z in Linux console when keypad() is used? */ - if (kbinput == 26 || kbinput == 407) { + /* Catch ^Z by hand when triggered also */ + if (kbinput == NANO_SUSPEND_KEY) { if (ISSET(SUSPEND)) do_suspend(0); keyhandled = 1; @@ -3734,18 +3561,10 @@ int main(int argc, char *argv[]) break; #endif - case -1: /* Stuff that we don't want to do squat */ - case 0: /* Erg */ - case 29: /* Ctrl-] */ - case 410: /* Must ignore this, it's sent when we resize */ -#ifdef PDCURSES - case 541: /* ???? */ - case 542: /* Control and alt in Windows *shrug* */ - case 543: /* Right ctrl key */ - case 544: - case 545: /* Right alt key */ -#endif - + case NANO_CONTROL_3: /* Ctrl-[ (Esc), which should + * have been handled before we + * got here */ + case NANO_CONTROL_5: /* Ctrl-] */ break; default: #ifdef DEBUG diff --git a/nano.h b/nano.h index b442503b..0444ab00 100644 --- a/nano.h +++ b/nano.h @@ -48,6 +48,7 @@ #include #define KEY_IC SL_KEY_IC #define KEY_DC SL_KEY_DELETE +#define KEY_SUSPEND -1 #elif defined(HAVE_NCURSES_H) #include #else /* Uh oh */ @@ -244,7 +245,7 @@ typedef struct historyheadtype { #define MAC_FILE (1<<20) #define SMOOTHSCROLL (1<<21) #define DISABLE_CURPOS (1<<22) /* Damn, we still need it */ -#define ALT_KEYPAD (1<<23) +#define REBIND_DELETE (1<<23) #define NO_CONVERT (1<<24) #define BACKUP_FILE (1<<25) #define NO_RCFILE (1<<26) @@ -283,11 +284,12 @@ typedef struct historyheadtype { #define NANO_CONTROL_X 24 #define NANO_CONTROL_Y 25 #define NANO_CONTROL_Z 26 - +#define NANO_CONTROL_3 27 #define NANO_CONTROL_4 28 #define NANO_CONTROL_5 29 #define NANO_CONTROL_6 30 #define NANO_CONTROL_7 31 +#define NANO_CONTROL_8 127 #define NANO_ALT_A 'a' #define NANO_ALT_B 'b' diff --git a/proto.h b/proto.h index 9ad6a42b..609d6c6e 100644 --- a/proto.h +++ b/proto.h @@ -424,6 +424,14 @@ int check_wildcard_match(const char *text, const char *pattern); #endif /* Public functions in winio.c */ +int get_kbinput(WINDOW *win, int *meta, int rebind_delete); +char *get_verbatim_kbinput(WINDOW *win, int *kbinput_len); +int get_ignored_kbinput(WINDOW *win); +int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta, + int rebind_delete); +int get_ascii_kbinput(WINDOW *win, int kbinput); +int get_escape_seq_kbinput(WINDOW *win, int kbinput); +int get_skip_tilde_kbinput(WINDOW *win, int errval, int retval); int do_first_line(void); int do_last_line(void); int xpt(const filestruct *fileptr, int index); @@ -482,7 +490,6 @@ int do_cursorpos(int constant); int do_cursorpos_void(void); int line_len(const char *ptr); int do_help(void); -int keypad_on(WINDOW *win, int newval); void do_replace_highlight(int highlight_flag, const char *word); void fix_editbot(void); #ifdef DEBUG diff --git a/rcfile.c b/rcfile.c index cbdd52b6..071b7654 100644 --- a/rcfile.c +++ b/rcfile.c @@ -49,7 +49,6 @@ const static rcoption rcopts[] = { #ifndef DISABLE_WRAPJUSTIFY {"fill", 0}, #endif - {"keypad", ALT_KEYPAD}, #if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION) {"mouse", USE_MOUSE}, #endif @@ -68,6 +67,7 @@ const static rcoption rcopts[] = { {"operatingdir", 0}, #endif {"preserve", PRESERVE}, + {"rebinddelete", REBIND_DELETE}, #ifndef DISABLE_JUSTIFY {"quotestr", 0}, #endif diff --git a/winio.c b/winio.c index dd72bcc3..1a759002 100644 --- a/winio.c +++ b/winio.c @@ -34,6 +34,295 @@ static int statblank = 0; /* Number of keystrokes left after we call statusbar(), before we actually blank the statusbar */ +/* Read in a single input character. If it's ignored, swallow it and go + * on. Otherwise, try to translate it from ASCII and extended (keypad) + * input. Assume nodelay(win) is FALSE. */ +int get_kbinput(WINDOW *win, int *meta, int rebind_delete) +{ + int kbinput, retval; + + kbinput = get_ignored_kbinput(win); + retval = get_accepted_kbinput(win, kbinput, meta, rebind_delete); + + 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. */ +char *get_verbatim_kbinput(WINDOW *win, int *kbinput_len) +{ + char *verbatim_kbinput; + int kbinput = wgetch(win); + + verbatim_kbinput = charalloc(1); + verbatim_kbinput[0] = kbinput; + *kbinput_len = 1; + + if (kbinput >= '0' && kbinput <= '2') + /* Entering a three-digit decimal ASCII code from 000-255 in + * verbatim mode will produce the corresponding ASCII + * character. */ + verbatim_kbinput[0] = (char)get_ascii_kbinput(win, kbinput); + else { + nodelay(win, TRUE); + while ((kbinput = wgetch(win)) != ERR) { + *kbinput_len++; + verbatim_kbinput = charealloc(verbatim_kbinput, *kbinput_len); + verbatim_kbinput[*kbinput_len - 1] = (char)kbinput; + } + nodelay(win, FALSE); + } + +#ifdef DEBUG + fprintf(stderr, "get_verbatim_kbinput(): verbatim_kbinput = %s\n", verbatim_kbinput); +#endif + return verbatim_kbinput; +} + +/* Swallow input characters that should be quietly ignored, and return + * the first input character that shouldn't be. */ +int get_ignored_kbinput(WINDOW *win) +{ + int kbinput; + + while (1) { + kbinput = wgetch(win); + switch (kbinput) { + case ERR: + case KEY_RESIZE: +#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; + } + } +} + +/* Translate acceptable ASCII and extended (keypad) input. Set meta to + * 1 if we get a Meta sequence. Assume nodelay(win) is FALSE. */ +int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta, + int rebind_delete) +{ + *meta = 0; + + switch (kbinput) { + case NANO_CONTROL_3: /* Escape */ + switch (kbinput = wgetch(win)) { + case NANO_CONTROL_3: /* Escape */ + kbinput = wgetch(win); + /* Esc Esc [three-digit decimal ASCII code from + * 000-255] == [corresponding ASCII character]; + Esc Esc 2 obviously can't be Ctrl-2 here */ + if (kbinput >= '0' && kbinput <= '2') + kbinput = get_ascii_kbinput(win, kbinput); + /* 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-Z */ + else if (kbinput >= 'a' && kbinput <= 'z') + kbinput -= 96; + break; + /* Terminal breakage, part 1: We shouldn't get an escape + * sequence here for terminals that support Delete, but + * we do sometimes on FreeBSD. Thank you, Wouter van + * Hemel. */ + case '[': + nodelay(win, TRUE); + kbinput = wgetch(win); + switch (kbinput) { + case ERR: + kbinput = '['; + *meta = 1; + break; + default: + kbinput = get_escape_seq_kbinput(win, kbinput); + break; + } + nodelay(win, FALSE); + break; + case '`': + /* Esc Space == Esc ` */ + kbinput = ' '; + break; + default: + /* Esc [character] == Meta-[character] */ + if (isupper(kbinput)) + kbinput = tolower(kbinput); + *meta = 1; + break; + } + break; + case KEY_DOWN: + kbinput = NANO_DOWN_KEY; + break; + case KEY_UP: + kbinput = NANO_UP_KEY; + break; + case KEY_LEFT: + kbinput = NANO_BACK_KEY; + break; + case KEY_RIGHT: + kbinput = NANO_FORWARD_KEY; + break; + case KEY_HOME: + kbinput = NANO_HOME_KEY; + break; + case KEY_BACKSPACE: + kbinput = NANO_BACKSPACE_KEY; + break; + case KEY_DC: + /* Terminal breakage, part 2: We should only get KEY_DC when + * hitting Delete, but we get it when hitting Backspace + * sometimes on FreeBSD. Thank you, Lee Nelson. */ + kbinput = (rebind_delete) ? NANO_BACKSPACE_KEY : NANO_DELETE_KEY; + break; + case KEY_IC: + kbinput = NANO_INSERTFILE_KEY; + break; + case KEY_NPAGE: + kbinput = NANO_NEXTPAGE_KEY; + break; + case KEY_PPAGE: + kbinput = NANO_PREVPAGE_KEY; + break; + case KEY_ENTER: + kbinput = NANO_ENTER_KEY; + break; + case KEY_END: + kbinput = NANO_END_KEY; + break; + case KEY_SUSPEND: + kbinput = NANO_SUSPEND_KEY; + break; + default: + break; + } +#ifdef DEBUG + fprintf(stderr, "get_accepted_kbinput(): kbinput = %d, meta = %d\n", kbinput, *meta); +#endif + return kbinput; +} + +/* Translate a three-digit decimal ASCII code from 000-255 into the + * corresponding ASCII character. */ +int get_ascii_kbinput(WINDOW *win, int kbinput) +{ + int retval; + + switch (kbinput) { + case '0': + case '1': + case '2': + retval = (kbinput - 48) * 100; + break; + default: + return kbinput; + } + + kbinput = wgetch(win); + switch (kbinput) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + retval += (kbinput - 48) * 10; + break; + case '6': + case '7': + case '8': + case '9': + if (retval < 200) { + retval += (kbinput - 48) * 10; + break; + } + default: + return kbinput; + } + + kbinput = wgetch(win); + switch (kbinput) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + retval += kbinput - 48; + break; + case '6': + case '7': + case '8': + case '9': + if (retval < 250) { + retval += kbinput - 48; + break; + } + default: + return kbinput; + } + +#ifdef DEBUG + fprintf(stderr, "get_ascii_kbinput(): kbinput = %d\n", kbinput); +#endif + return retval; +} + +/* Translate common escape sequences for some keys. These are generated + * when the terminal doesn't support those keys. Assume nodelay(win) is + * TRUE. */ +int get_escape_seq_kbinput(WINDOW *win, int kbinput) +{ + switch (kbinput) { + case '3': + /* Esc [ 3 ~ == kdch1 on many terminals. */ + kbinput = get_skip_tilde_kbinput(win, kbinput, NANO_DELETE_KEY); + break; + default: + break; + } + return kbinput; +} + +/* If there is no next character, return the passed-in error value. If + * the next character's a tilde, eat it and return the passed-in + * return value. Otherwise, return the next character. Assume + * nodelay(win) is TRUE. */ +int get_skip_tilde_kbinput(WINDOW *win, int errval, int retval) +{ + int kbinput = wgetch(win); + switch (kbinput) { + case ERR: + return errval; + case '~': + return retval; + default: + return kbinput; + } +} + int do_first_line(void) { current = fileage; @@ -197,6 +486,7 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, ) { int kbinput; + int meta; static int x = -1; /* the cursor position in 'answer' */ int xend; @@ -247,7 +537,7 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, input */ wrefresh(edit); - while ((kbinput = wgetch(bottomwin)) != 13) { + while ((kbinput = get_kbinput(bottomwin, &meta, ISSET(REBIND_DELETE))) != NANO_ENTER_KEY) { for (t = s; t != NULL; t = t->next) { #ifdef DEBUG fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput); @@ -273,64 +563,45 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, tabbed = 0; switch (kbinput) { - - /* Stuff we want to equate with , ASCII 13 */ - case 343: - ungetch(13); /* Enter on iris-ansi $TERM, sometimes */ - break; - /* Stuff we want to ignore */ -#ifdef PDCURSES - case 541: - case 542: - case 543: /* Right ctrl again */ - case 544: - case 545: /* Right alt again */ - break; -#endif #if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION) case KEY_MOUSE: do_mouse(); break; #endif case NANO_HOME_KEY: - case KEY_HOME: x = 0; break; case NANO_END_KEY: - case KEY_END: x = xend; break; - case KEY_RIGHT: case NANO_FORWARD_KEY: if (x < xend) x++; break; - case NANO_CONTROL_D: + case NANO_DELETE_KEY: if (x < xend) { memmove(answer + x, answer + x + 1, xend - x); xend--; } break; - case NANO_CONTROL_K: - case NANO_CONTROL_U: + case NANO_CUT_KEY: + case NANO_UNCUT_KEY: null_at(&answer, 0); xend = 0; x = 0; break; - case KEY_BACKSPACE: - case 127: - case NANO_CONTROL_H: + case NANO_BACKSPACE_KEY: if (x > 0) { memmove(answer + x - 1, answer + x, xend - x + 1); x--; xend--; } break; - case NANO_CONTROL_I: + case NANO_TAB_KEY: #ifndef NANO_SMALL /* tab history completion */ if (history_list != NULL) { - if (!complete || last_kbinput != NANO_CONTROL_I) { + if (!complete || last_kbinput != NANO_TAB_KEY) { history_list->current = (historytype *)history_list; history_list->len = strlen(answer); } @@ -358,15 +629,12 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, } #endif break; - case KEY_LEFT: case NANO_BACK_KEY: if (x > 0) x--; break; - case KEY_UP: case NANO_UP_KEY: #ifndef NANO_SMALL - do_upkey: if (history_list != NULL) { /* if currentbuf is NULL, or if use_cb is 1, currentbuf @@ -407,10 +675,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, } #endif break; - case KEY_DOWN: case NANO_DOWN_KEY: #ifndef NANO_SMALL - do_downkey: if (history_list != NULL) { /* get newer search from the history list and save it @@ -452,71 +718,6 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, } #endif break; - case KEY_DC: - goto do_deletekey; - case 27: - switch (kbinput = wgetch(edit)) { - case 'O': - switch (kbinput = wgetch(edit)) { - case 'F': - x = xend; - break; - case 'H': - x = 0; - break; - } - break; - case '[': - switch (kbinput = wgetch(edit)) { - case 'A': -#ifndef NANO_SMALL - goto do_upkey; -#else - break; -#endif - case 'B': -#ifndef NANO_SMALL - goto do_downkey; -#else - break; -#endif - case 'C': - if (x < xend) - x++; - break; - case 'D': - if (x > 0) - x--; - break; - case 'F': - x = xend; - break; - case 'H': - x = 0; - break; - case '1': - case '7': - x = 0; - goto skip_tilde; - case '3': - do_deletekey: - if (x < xend) { - memmove(answer + x, answer + x + 1, xend - x); - xend--; - } - goto skip_tilde; - case '4': - case '8': - x = xend; - skip_tilde: - nodelay(edit, TRUE); - kbinput = wgetch(edit); - if (kbinput == '~' || kbinput == ERR) - kbinput = -1; - nodelay(edit, FALSE); - break; - } - break; default: for (t = s; t != NULL; t = t->next) { @@ -524,17 +725,14 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput); #endif - if (kbinput == t->val || kbinput == t->val - 32) + if (meta == 1 && (kbinput == t->val || kbinput == t->val - 32)) /* We hit an Alt key. Do like above. We don't just ungetch() the letter and let it get caught above cause that screws the keypad... */ return t->val; } - } - break; - default: if (kbinput < 32) break; answer = charealloc(answer, xend + 2); @@ -1546,7 +1744,7 @@ int line_len(const char *ptr) int do_help(void) { #ifndef DISABLE_HELP - int i, page = 0, kbinput = 0, no_more = 0, kp; + int i, page = 0, kbinput = -1, meta, no_more = 0; int no_help_flag = 0; const shortcut *oldshortcut; @@ -1563,8 +1761,6 @@ int do_help(void) currshortcut = help_list; - kp = keypad_on(edit, 1); - if (ISSET(NO_HELP)) { /* Well, if we're going to do this, we should at least @@ -1586,32 +1782,8 @@ int do_help(void) do_mouse(); break; #endif - case 27: - kbinput = wgetch(edit); - switch(kbinput) { - case '[': - kbinput = wgetch(edit); - switch(kbinput) { - case '5': /* Alt-[-5 = Page Up */ - wgetch(edit); - goto do_pageupkey; - case 'V': /* Alt-[-V = Page Up in Hurd Console */ - case 'I': /* Alt-[-I = Page Up - FreeBSD Console */ - goto do_pageupkey; - case '6': /* Alt-[-6 = Page Down */ - wgetch(edit); - goto do_pagedownkey; - case 'U': /* Alt-[-U = Page Down in Hurd Console */ - case 'G': /* Alt-[-G = Page Down - FreeBSD Console */ - goto do_pagedownkey; - } - break; - } - break; case NANO_NEXTPAGE_KEY: case NANO_NEXTPAGE_FKEY: - case KEY_NPAGE: - do_pagedownkey: if (!no_more) { blank_edit(); page++; @@ -1619,8 +1791,6 @@ int do_help(void) break; case NANO_PREVPAGE_KEY: case NANO_PREVPAGE_FKEY: - case KEY_PPAGE: - do_pageupkey: if (page > 0) { no_more = 0; blank_edit(); @@ -1649,8 +1819,7 @@ int do_help(void) no_more = 1; continue; } - } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY && - kbinput != NANO_EXIT_FKEY); + } while ((kbinput = get_kbinput(edit, &meta, ISSET(REBIND_DELETE))) != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY); currshortcut = oldshortcut; @@ -1664,7 +1833,6 @@ int do_help(void) curs_set(1); edit_refresh(); - kp = keypad_on(edit, kp); /* The help_init() at the beginning allocated help_text, which has now been written to screen. */ @@ -1678,19 +1846,6 @@ int do_help(void) return 1; } -int keypad_on(WINDOW *win, int newval) -{ -/* This is taken right from aumix. Don't sue me. */ -#ifdef HAVE_USEKEYPAD - int old = win->_use_keypad; - keypad(win, newval); - return old; -#else - keypad(win, newval); - return 1; -#endif /* HAVE_USEKEYPAD */ -} - /* Highlight the current word being replaced or spell checked. */ void do_replace_highlight(int highlight_flag, const char *word) {