diff -urp readline-7-0/callback.c readline-7.0/callback.c --- readline-7-0/callback.c 2016-07-18 06:17:04 +1000 +++ readline-7.0/callback.c 2016-07-18 06:17:04 +1000 @@ -60,7 +60,7 @@ int rl_persistent_signal_handlers = 0; /* **************************************************************** */ /* */ -/* Callback Readline Functions */ +/* Callback Readline Functions */ /* */ /* **************************************************************** */ diff -urp readline-7-0/chardefs.h readline-7.0/chardefs.h --- readline-7-0/chardefs.h 2016-01-26 01:37:46 +1000 +++ readline-7.0/chardefs.h 2017-02-18 11:39:58 +1000 @@ -58,7 +58,11 @@ #define largest_char 255 /* Largest character value. */ #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0)) +#if !defined (_WIN32) #define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char) +#else +#define META_CHAR(c) 0 +#endif #define CTRL(c) ((c) & control_character_mask) #define META(c) ((c) | meta_character_bit) diff -urp readline-7-0/complete.c readline-7.0/complete.c --- readline-7-0/complete.c 2016-04-25 09:39:32 +1000 +++ readline-7.0/complete.c 2017-02-20 21:38:19 +1000 @@ -288,7 +288,11 @@ int _rl_page_completions = 1; /* The basic list of characters that signal a break between words for the completer routine. The contents of this variable is what breaks words in the shell, i.e. " \t\n\"\\'`@$><=" */ +#if defined (__MSDOS__) || defined (_WIN32) +const char *rl_basic_word_break_characters = " \t\n\"'`@$><=;|&{("; /* }) */ +#else const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */ +#endif /* List of basic quoting characters. */ const char *rl_basic_quote_characters = "\"'"; @@ -720,7 +724,7 @@ printable_part (pathname) if (rl_filename_completion_desired == 0) /* don't need to do anything */ return (pathname); - temp = strrchr (pathname, '/'); + temp = _rl_last_path_sep (pathname); #if defined (__MSDOS__) || defined (_WIN32) if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') temp = pathname + 1; @@ -737,9 +741,9 @@ printable_part (pathname) else if (temp[1] == '\0') { for (x = temp - 1; x > pathname; x--) - if (*x == '/') + if (_rl_is_path_sep (*x)) break; - return ((*x == '/') ? x + 1 : pathname); + return (_rl_is_path_sep (*x) ? x + 1 : pathname); } else return ++temp; @@ -967,13 +971,20 @@ print_filename (to_print, full_pathname, bash directory completion hook, for example, it will expand it to the current directory. We just want the `/'. */ if (full_pathname == 0 || *full_pathname == 0) - dn = "/"; - else if (full_pathname[0] != '/') + dn = _rl_path_sep_str; + else if (!_rl_is_path_sep (full_pathname[0])) dn = full_pathname; else if (full_pathname[1] == 0) - dn = "//"; /* restore trailing slash to `//' */ - else if (full_pathname[1] == '/' && full_pathname[2] == 0) - dn = "/"; /* don't turn /// into // */ + { +#if defined (__MSDOS__) || defined (_WIN32) + if (_rl_path_sep_chr == '\\') + dn = "\\\\"; + else +#endif + dn = "//"; /* restore trailing slash to `//' */ + } + else if (_rl_is_path_sep (full_pathname[1]) && full_pathname[2] == 0) + dn = _rl_path_sep_str; /* don't turn /// into // */ else dn = full_pathname; s = tilde_expand (dn); @@ -984,11 +995,10 @@ print_filename (to_print, full_pathname, tlen = strlen (to_print); new_full_pathname = (char *)xmalloc (slen + tlen + 2); strcpy (new_full_pathname, s); - if (s[slen - 1] == '/') + if (_rl_is_path_sep (s[slen - 1])) slen--; else - new_full_pathname[slen] = '/'; - new_full_pathname[slen] = '/'; + new_full_pathname[slen] = _rl_path_sep_chr; strcpy (new_full_pathname + slen + 1, to_print); #if defined (VISIBLE_STATS) @@ -1573,7 +1583,7 @@ rl_display_match_list (matches, len, max { t = printable_part (matches[0]); /* check again in case of /usr/src/ */ - temp = rl_filename_completion_desired ? strrchr (t, '/') : 0; + temp = rl_filename_completion_desired ? _rl_last_path_sep (t) : 0; common_length = temp ? fnwidth (temp) : fnwidth (t); sind = temp ? strlen (temp) : strlen (t); if (common_length > max || sind > max) @@ -1588,7 +1598,7 @@ rl_display_match_list (matches, len, max else if (_rl_colored_completion_prefix > 0) { t = printable_part (matches[0]); - temp = rl_filename_completion_desired ? strrchr (t, '/') : 0; + temp = rl_filename_completion_desired ? _rl_last_path_sep (t) : 0; common_length = temp ? fnwidth (temp) : fnwidth (t); sind = temp ? RL_STRLEN (temp+1) : RL_STRLEN (t); /* want portion after final slash */ if (common_length > max || sind > max) @@ -1930,10 +1940,10 @@ append_to_match (text, delimiter, quote_ /* This is clumsy. Avoid putting in a double slash if point is at the end of the line and the previous character is a slash. */ - if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') + if (rl_point && rl_line_buffer[rl_point] == '\0' && _rl_is_path_sep (rl_line_buffer[rl_point - 1])) ; - else if (rl_line_buffer[rl_point] != '/') - rl_insert_text ("/"); + else if (!_rl_is_path_sep (rl_line_buffer[rl_point])) + rl_insert_text (_rl_path_sep_str); } } #ifdef S_ISLNK @@ -2143,6 +2153,9 @@ rl_complete_internal (what_to_do) break; case '?': +#if defined (_WIN32) + display_matches (matches); +#else if (rl_completion_display_matches_hook == 0) { _rl_sigcleanup = _rl_complete_sigcleanup; @@ -2159,6 +2172,7 @@ rl_complete_internal (what_to_do) } _rl_sigcleanup = 0; _rl_sigcleanarg = 0; +#endif break; default: @@ -2505,7 +2519,7 @@ rl_filename_completion_function (text, s text = "."; dirname = savestring (text); - temp = strrchr (dirname, '/'); + temp = _rl_last_path_sep (dirname); #if defined (__MSDOS__) || defined (_WIN32) /* special hack for //X/... */ @@ -2664,9 +2678,9 @@ rl_filename_completion_function (text, s strcpy (temp, dirname); /* Canonicalization cuts off any final slash present. We may need to add it back. */ - if (dirname[dirlen - 1] != '/') + if (!_rl_is_path_sep (dirname[dirlen - 1])) { - temp[dirlen++] = '/'; + temp[dirlen++] = _rl_path_sep_chr; temp[dirlen] = '\0'; } } @@ -2676,8 +2690,11 @@ rl_filename_completion_function (text, s temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); strcpy (temp, users_dirname); /* Make sure that temp has a trailing slash here. */ - if (users_dirname[dirlen - 1] != '/') - temp[dirlen++] = '/'; +#if defined (__MSDOS__) || defined (_WIN32) + if (users_dirname[dirlen - 1] != ':') +#endif + if (!_rl_is_path_sep (users_dirname[dirlen - 1])) + temp[dirlen++] = _rl_path_sep_chr; } strcpy (temp + dirlen, convfn); diff -urp readline-7-0/configure readline-7.0/configure --- readline-7-0/configure 2016-09-08 07:15:16 +1000 +++ readline-7.0/configure 2017-02-21 10:11:15 +1000 @@ -5889,6 +5889,7 @@ _ACEOF case "$host_os" in aix*) prefer_curses=yes ;; +mingw*) bash_cv_termcap_lib=libc ;; esac if test "X$bash_cv_termcap_lib" = "X"; then diff -urp readline-7-0/display.c readline-7.0/display.c --- readline-7-0/display.c 2016-07-29 04:49:33 +1000 +++ readline-7.0/display.c 2017-02-06 17:58:00 +1000 @@ -59,6 +59,14 @@ #include "rlprivate.h" #include "xmalloc.h" +#if defined (_WIN32) +#include +extern int haveConsole; +extern HANDLE hStdout, hStdin; +extern COORD rlScreenOrigin, rlScreenEnd; +extern int rlScreenStart, rlScreenMax; +#endif /* _WIN32 */ + #if !defined (strchr) && !defined (__STDC__) extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ @@ -104,6 +112,11 @@ static int line_structures_initialized = #define visible_line (line_state_visible->line) #define invisible_line (line_state_invisible->line) +#if defined (_WIN32) +#define putc(ch, stream) \ + if ((ch) == '\r') cr (); else _rl_output_character_function (ch) +#endif + #if defined (HANDLE_MULTIBYTE) static int _rl_col_width PARAMS((const char *, int, int, int)); #else @@ -1189,7 +1202,7 @@ rl_redisplay () _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) #endif { -#if defined (__MSDOS__) +#if defined (__MSDOS__) || defined (_WIN32) putc ('\r', rl_outstream); #else if (_rl_term_cr) @@ -1682,7 +1695,7 @@ update_line (old, new, current_line, oma (((od > 0 || nd > 0) && (od <= prompt_last_invisible || nd <= prompt_last_invisible)) || ((od >= lendiff) && _rl_last_c_pos < PROMPT_ENDING_INDEX))) { -#if defined (__MSDOS__) +#if defined (__MSDOS__) || defined (_WIN32) putc ('\r', rl_outstream); #else tputs (_rl_term_cr, 1, _rl_output_character_function); @@ -1800,6 +1813,7 @@ update_line (old, new, current_line, oma /* col_lendiff > 0 if we are adding characters to the line */ if (col_lendiff > 0) /* XXX - was lendiff */ { +#if !defined (_WIN32) /* Non-zero if we're increasing the number of lines. */ int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin; /* If col_lendiff is > 0, implying that the new string takes up more @@ -1889,6 +1903,7 @@ update_line (old, new, current_line, oma } } else +#endif /* !_WIN32 */ { /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); @@ -1914,6 +1929,7 @@ update_line (old, new, current_line, oma } else /* Delete characters from line. */ { +#if !defined (_WIN32) /* If possible and inexpensive to use terminal deletion, then do so. */ if (_rl_term_dc && (2 * col_temp) >= -col_lendiff) { @@ -1971,6 +1987,7 @@ update_line (old, new, current_line, oma } /* Otherwise, print over the existing material. */ else +#endif /* !_WIN32 */ { if (temp > 0) { @@ -2038,7 +2055,7 @@ rl_clear_visible_line () int curr_line; /* Make sure we move to column 0 so we clear the entire line */ -#if defined (__MSDOS__) +#if defined (__MSDOS__) || defined (_WIN32) putc ('\r', rl_outstream); #else tputs (_rl_term_cr, 1, _rl_output_character_function); @@ -2159,6 +2176,17 @@ _rl_move_cursor_relative (new, data) int new; const char *data; { +#if defined (_WIN32) + CONSOLE_SCREEN_BUFFER_INFO csbi; + /* 0 is used for CR, so do it absolutely, because of the pager. */ + if ((_rl_last_c_pos != new || new == 0) + && haveConsole && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + csbi.dwCursorPosition.X = new; + if (SetConsoleCursorPosition (hStdout, csbi.dwCursorPosition)) + _rl_last_c_pos = new; + } +#else /* _WIN32 */ register int i; int woff; /* number of invisible chars on current line */ int cpos, dpos; /* current and desired cursor positions */ @@ -2310,6 +2338,7 @@ _rl_move_cursor_relative (new, data) _rl_backspace (cpos - dpos); _rl_last_c_pos = dpos; +#endif /* !_WIN32 */ } /* PWP: move the cursor up or down. */ @@ -2317,6 +2346,16 @@ void _rl_move_vert (to) int to; { +#if defined (_WIN32) + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (_rl_last_v_pos != to && to <= _rl_screenheight + && haveConsole && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + csbi.dwCursorPosition.Y += to - _rl_last_v_pos; + if (SetConsoleCursorPosition (hStdout, csbi.dwCursorPosition)) + _rl_last_v_pos = to; + } +#else /* !_WIN32 */ register int delta, i; if (_rl_last_v_pos == to || to > _rl_screenheight) @@ -2350,6 +2389,7 @@ _rl_move_vert (to) } _rl_last_v_pos = to; /* Now TO is here */ +#endif /* _WIN32 */ } /* Physically print C on rl_outstream. This is for functions which know @@ -2636,11 +2676,28 @@ _rl_erase_at_end_of_line (l) } /* Clear to the end of the line. COUNT is the minimum - number of character spaces to clear, */ + number of character spaces to clear. */ void _rl_clear_to_eol (count) int count; { +#if defined (_WIN32) + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (haveConsole && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + DWORD written; + int linear_pos; + + linear_pos = (int)csbi.dwCursorPosition.Y * (int)csbi.dwSize.X + + (int)csbi.dwCursorPosition.X; + if (linear_pos < rlScreenMax) + { + rlScreenEnd = csbi.dwCursorPosition; + rlScreenMax = linear_pos; + } + FillConsoleOutputCharacter (hStdout, ' ', count, csbi.dwCursorPosition, &written); + } +#else /* !_WIN32 */ #ifndef __MSDOS__ if (_rl_term_clreol) tputs (_rl_term_clreol, 1, _rl_output_character_function); @@ -2648,25 +2705,74 @@ _rl_clear_to_eol (count) #endif if (count) space_to_eol (count); +#endif /* _WIN32 */ } /* Clear to the end of the line using spaces. COUNT is the minimum - number of character spaces to clear, */ + number of character spaces to clear. */ static void space_to_eol (count) int count; { +#if defined (_WIN32) + _rl_clear_to_eol (count); +#else register int i; for (i = 0; i < count; i++) - putc (' ', rl_outstream); + putc (' ', rl_outstream); _rl_last_c_pos += count; +#endif /* _WIN32 */ } void _rl_clear_screen () { +#if defined (_WIN32) + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (haveConsole && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + DWORD written; + + if (rlScreenOrigin.Y != csbi.srWindow.Top + || csbi.srWindow.Bottom == csbi.dwSize.Y - 1) + { + /* Rather than clearing the existing window, make the current + line the new top of the window. */ + int range = csbi.srWindow.Bottom - csbi.srWindow.Top; + if (rlScreenOrigin.Y + range < csbi.dwSize.Y) + { + csbi.srWindow.Top = rlScreenOrigin.Y; + csbi.srWindow.Bottom = csbi.srWindow.Top + range; + } + else + { + SMALL_RECT sr; + CHAR_INFO ci; + csbi.srWindow.Bottom = csbi.dwSize.Y - 1; + csbi.srWindow.Top = csbi.srWindow.Bottom - range; + sr.Left = 0; + sr.Right = csbi.dwSize.X - 1; + sr.Top = rlScreenOrigin.Y - csbi.srWindow.Top; + sr.Bottom = rlScreenOrigin.Y - 1; + csbi.dwCursorPosition.X = csbi.dwCursorPosition.Y = 0; + ci.Char.AsciiChar = ' '; + ci.Attributes = csbi.wAttributes; + ScrollConsoleScreenBuffer (hStdout, &sr, NULL, csbi.dwCursorPosition, &ci); + rlScreenOrigin.Y = csbi.srWindow.Top; + rlScreenStart = (int)rlScreenOrigin.Y * (int)csbi.dwSize.X; + rlScreenMax = 0; + } + SetConsoleWindowInfo (hStdout, TRUE, &csbi.srWindow); + } + csbi.dwCursorPosition.X = 0; + csbi.dwCursorPosition.Y = csbi.srWindow.Top; + written = (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * csbi.dwSize.X; + FillConsoleOutputCharacter (hStdout, ' ', written, csbi.dwCursorPosition, &written); + SetConsoleCursorPosition (hStdout, csbi.dwCursorPosition); + } +#else #ifndef __DJGPP__ if (_rl_term_clrpag) tputs (_rl_term_clrpag, 1, _rl_output_character_function); @@ -2676,8 +2782,10 @@ _rl_clear_screen () ScreenClear (); ScreenSetCursor (0, 0); #endif /* __DJGPP__ */ +#endif /* _WIN32 */ } +#if !defined (_WIN32) /* Insert COUNT characters from STRING to the output stream at column COL. */ static void insert_some_chars (string, count, col) @@ -2750,6 +2858,7 @@ delete_chars (count) } #endif /* !__MSDOS__ && (!__MINGW32__ || NCURSES_VERSION)*/ } +#endif /* !_WIN32 */ void _rl_update_final () @@ -2787,6 +2896,9 @@ _rl_update_final () static void cr () { +#if defined (_WIN32) + _rl_move_cursor_relative (0, 0); +#else if (_rl_term_cr) { #if defined (__MSDOS__) @@ -2796,6 +2908,7 @@ cr () #endif _rl_last_c_pos = 0; } +#endif /* _WIN32 */ } /* Redraw the last line of a multi-line prompt that may possibly contain @@ -2839,7 +2952,11 @@ _rl_redisplay_after_sigwinch () { _rl_move_vert (_rl_vis_botlin); -#if defined (__MSDOS__) +#if defined (_WIN32) + _rl_move_cursor_relative (0, 0); + space_to_eol (_rl_screenwidth); + _rl_move_cursor_relative (0, 0); +#elif defined (__MSDOS__) putc ('\r', rl_outstream); #else tputs (_rl_term_cr, 1, _rl_output_character_function); @@ -2848,7 +2965,7 @@ _rl_redisplay_after_sigwinch () #if defined (__MSDOS__) space_to_eol (_rl_screenwidth); putc ('\r', rl_outstream); -#else +#elif !defined (_WIN32) if (_rl_term_clreol) tputs (_rl_term_clreol, 1, _rl_output_character_function); else diff -urp readline-7-0/examples/Makefile.in readline-7.0/examples/Makefile.in --- readline-7-0/examples/Makefile.in 2016-04-26 23:50:18 +1000 +++ readline-7.0/examples/Makefile.in 2017-02-21 10:20:40 +1000 @@ -135,7 +135,7 @@ hist_erasedups$(EXEEXT): hist_erasedups. $(CC) $(LDFLAGS) -o $@ hist_erasedups.o -lhistory $(TERMCAP_LIB) hist_purgecmd$(EXEEXT): hist_purgecmd.o $(HISTORY_LIB) - $(CC) $(LDFLAGS) -o $@ hist_purgecmd.o -lhistory $(TERMCAP_LIB) + $(CC) $(LDFLAGS) -o $@ hist_purgecmd.o -lhistory $(TERMCAP_LIB) -lgnurx clean mostlyclean: $(RM) $(OBJECTS) $(OTHEROBJ) diff -urp readline-7-0/examples/rl-callbacktest.c readline-7.0/examples/rl-callbacktest.c --- readline-7-0/examples/rl-callbacktest.c 2016-04-27 00:05:31 +1000 +++ readline-7.0/examples/rl-callbacktest.c 2017-02-14 09:51:24 +1000 @@ -6,7 +6,13 @@ /* Used for select(2) */ #include +#if !defined (_WIN32) #include +#else +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif #include @@ -69,14 +75,18 @@ cb_linehandler (char *line) int main (int c, char **v) { +#if !defined (_WIN32) fd_set fds; +#endif int r; setlocale (LC_ALL, ""); /* Handle SIGWINCH */ +#if !defined (_WIN32) signal (SIGWINCH, sighandler); +#endif /* Install the line handler. */ rl_callback_handler_install (prompt, cb_linehandler); @@ -88,11 +98,17 @@ main (int c, char **v) running = 1; while (running) { +#if !defined (_WIN32) FD_ZERO (&fds); FD_SET (fileno (rl_instream), &fds); r = select (FD_SETSIZE, &fds, NULL, NULL, NULL); if (r < 0 && errno != EINTR) +#else + while (!_kbhit ()) + Sleep (50); + if ((r = 0)) +#endif { perror ("rltest: select"); rl_callback_handler_remove (); @@ -106,7 +122,9 @@ main (int c, char **v) if (r < 0) continue; +#if !defined (_WIN32) if (FD_ISSET (fileno (rl_instream), &fds)) +#endif rl_callback_read_char (); } diff -urp readline-7-0/histexpand.c readline-7.0/histexpand.c --- readline-7-0/histexpand.c 2016-08-11 21:55:53 +1000 +++ readline-7.0/histexpand.c 2017-02-20 18:27:15 +1000 @@ -40,6 +40,9 @@ # include #endif +#include "readline.h" +#include "rlprivate.h" + #include "rlmbutil.h" #include "history.h" @@ -107,6 +110,11 @@ char *history_word_delimiters = HISTORY_ particular history expansion should be performed. */ rl_linebuf_func_t *history_inhibit_expansion_function; +/* The character to use as path separator. */ +#if defined (__MSDOS__) || defined (_WIN32) +char _rl_path_sep_str[] = "\\"; +#endif + /* **************************************************************** */ /* */ /* History Expansion */ @@ -521,6 +529,26 @@ postproc_subst_rhs () subst_rhs_len = j; } +#if defined (__MSDOS__) || defined (_WIN32) +char * +_rl_last_path_sep (filename) + const char *filename; +{ + const char *dirname = NULL; + _rl_path_sep_chr = '\\'; + while (*filename) + { + if (_rl_is_path_sep (*filename)) + { + _rl_path_sep_chr = *filename; + dirname = filename; + } + filename++; + } + return (char *)dirname; +} +#endif + /* Expand the bulk of a history specifier starting at STRING[START]. Returns 0 if everything is OK, -1 if an error occurred, and 1 if the `p' modifier was supplied and the caller should just print @@ -638,7 +666,7 @@ history_expand_internal (string, start, /* :t discards all but the last part of the pathname. */ case 't': - tstr = strrchr (temp, '/'); + tstr = _rl_last_path_sep (temp); if (tstr) { tstr++; @@ -650,7 +678,7 @@ history_expand_internal (string, start, /* :h discards the last part of a pathname. */ case 'h': - tstr = strrchr (temp, '/'); + tstr = _rl_last_path_sep (temp); if (tstr) *tstr = '\0'; break; diff -urp readline-7-0/histfile.c readline-7.0/histfile.c --- readline-7-0/histfile.c 2016-01-26 01:34:03 +1000 +++ readline-7.0/histfile.c 2017-02-02 10:08:57 +1000 @@ -79,18 +79,22 @@ #endif /* HISTORY_USE_MMAP */ +#if defined (_WIN32) +#include +#endif + /* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment on win 95/98/nt), we want to open files with O_BINARY mode so that there is no \n -> \r\n conversion performed. On other systems, we don't want to mess around with O_BINARY at all, so we ensure that it's defined to 0. */ -#if defined (__EMX__) || defined (__CYGWIN__) +#if defined (__EMX__) || defined (__CYGWIN__) || defined (_WIN32) # ifndef O_BINARY # define O_BINARY 0 # endif -#else /* !__EMX__ && !__CYGWIN__ */ +#else /* !__EMX__ && !__CYGWIN__ && !_WIN32 */ # undef O_BINARY # define O_BINARY 0 -#endif /* !__EMX__ && !__CYGWIN__ */ +#endif /* !__EMX__ && !__CYGWIN__ && !_WIN32 */ #include #if !defined (errno) @@ -610,8 +614,10 @@ history_truncate_file (fname, lines) user is running this, it's a no-op. If the shell is running after sudo with a shared history file, we don't want to leave the history file owned by root. */ +#if defined (HAVE_CHOWN) if (rv == 0 && exists) r = chown (filename, finfo.st_uid, finfo.st_gid); +#endif xfree (filename); FREE (tempname); @@ -757,8 +763,10 @@ mmap_error: user is running this, it's a no-op. If the shell is running after sudo with a shared history file, we don't want to leave the history file owned by root. */ +#if defined (HAVE_CHOWN) if (rv == 0 && exists) mode = chown (histname, finfo.st_uid, finfo.st_gid); +#endif FREE (histname); FREE (tempname); diff -urp readline-7-0/histlib.h readline-7.0/histlib.h --- readline-7-0/histlib.h 2016-04-23 01:03:20 +1000 +++ readline-7.0/histlib.h 2017-02-02 10:08:57 +1000 @@ -51,7 +51,7 @@ #endif #ifndef member -# ifndef strchr +# if !defined (strchr) && !defined (__STDC__) extern char *strchr (); # endif #define member(c, s) ((c) ? ((char *)strchr ((s), (c)) != (char *)NULL) : 0) diff -urp readline-7-0/input.c readline-7.0/input.c --- readline-7-0/input.c 2016-08-31 00:21:47 +1000 +++ readline-7.0/input.c 2017-02-19 22:20:22 +1000 @@ -95,20 +95,12 @@ static int ibuffer_space PARAMS((void)); static int rl_get_char PARAMS((int *)); static int rl_gather_tyi PARAMS((void)); -/* Windows isatty returns true for every character device, including the null - device, so we need to perform additional checks. */ #if defined (_WIN32) && !defined (__CYGWIN__) -#include #define WIN32_LEAN_AND_MEAN 1 #include -int -win32_isatty (int fd) -{ - return (_isatty (fd) ? ((((long) (HANDLE) _get_osfhandle (fd)) & 3) == 3) : 0); -} +static int pending_count = 0; -#define isatty(x) win32_isatty(x) #endif /* **************************************************************** */ @@ -247,9 +239,7 @@ rl_gather_tyi () #endif /* O_NDELAY */ #if defined (__MINGW32__) - /* Use getch/_kbhit to check for available console input, in the same way - that we read it normally. */ - chars_avail = isatty (tty) ? _kbhit () : 0; + chars_avail = pending_count; result = 0; #endif @@ -344,8 +334,7 @@ _rl_input_available () #endif #if defined (__MINGW32__) - if (isatty (tty)) - return (_kbhit ()); + return (pending_count); #endif return 0; @@ -489,6 +478,7 @@ rl_read_key () return (c); } +#if !defined (_WIN32) int rl_getc (stream) FILE *stream; @@ -506,10 +496,6 @@ rl_getc (stream) /* We know at this point that _rl_caught_signal == 0 */ -#if defined (__MINGW32__) - if (isatty (fileno (stream))) - return (_getch ()); /* "There is no error return." */ -#endif result = 0; #if defined (HAVE_PSELECT) sigemptyset (&empty_set); @@ -598,6 +584,258 @@ handle_error: (*rl_signal_event_hook) (); } } +#else /* _WIN32 */ + +#define EXT_PREFIX 0xf8 + +#define KEV irec.Event.KeyEvent /* to make life easier */ +#define KST irec.Event.KeyEvent.dwControlKeyState + + +static int pending_esc = 0; +static int pending_prefix = 0; +static int pending_key = 0; + +extern int _rl_last_c_pos; /* imported from display.c */ +extern int _rl_last_v_pos; +extern int rl_dispatching; /* imported from readline.c */ +extern int rl_point; +extern int rl_done; +extern int rl_visible_prompt_length; +extern int _rl_screenwidth; /* imported from terminal.c */ + +extern int haveConsole; /* imported from rltty.c */ +extern HANDLE hStdout, hStdin; +extern COORD rlScreenOrigin, rlScreenEnd; +extern int rlScreenStart, rlScreenMax; +static void MouseEventProc (MOUSE_EVENT_RECORD kev); + +int +rl_getc (stream) + FILE *stream; +{ + int key; + + if (pending_count) + { + --pending_count; + if (pending_prefix) + { + switch (pending_count % 3) + { + case 2: key = ESC; break; + case 1: key = pending_prefix; break; + case 0: key = pending_key; break; + } + } + else if (pending_esc) + key = (pending_count & 1) ? ESC : pending_key; + else + key = pending_key; + return key; + } + + while (1) + { + DWORD dummy; + + if (WaitForSingleObject (hStdin, WAIT_FOR_INPUT) != WAIT_OBJECT_0) + { + if (rl_done) + return (0); + else + continue; + } + if (haveConsole & FOR_INPUT) + { + INPUT_RECORD irec; + ReadConsoleInput (hStdin, &irec, 1, &dummy); + switch (irec.EventType) + { + case KEY_EVENT: + if (KEV.bKeyDown + && (KEV.wVirtualKeyCode < VK_SHIFT || KEV.wVirtualKeyCode > VK_MENU)) + { + pending_esc = pending_prefix = 0; + + key = KEV.uChar.AsciiChar & 0xff; + if (KST & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) + { + pending_esc = 1; + /* Translate Ctrl+Alt to Alt+Ctrl. */ + if (KST & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + { + key = KEV.wVirtualKeyCode; + if (key == '2') + key = 0; + else if (key >= 'A' && key <= 'Z') + key -= 'A' - 1; + else if (key >= VK_OEM_4 && key <= VK_OEM_6) + key -= VK_OEM_4 - 27; + else if (key == '6') + key = 30; + else if (key == VK_OEM_MINUS) + key = 31; + else + key = 0; + } + } + else if (key == 0 + && (KST & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))) + { + /* Translate Ctrl+2, Ctrl+6 & Ctrl+- to C-@, C-^ & C-_. */ + /*if (KEV.wVirtualKeyCode == '2') + key = 0; + else*/ if (KEV.wVirtualKeyCode == '6') + key = 30; + else if (KEV.wVirtualKeyCode == VK_OEM_MINUS) + key = 31; + } + else if ((KEV.wVirtualKeyCode == VK_ESCAPE +#if defined (VI_MODE) + && rl_editing_mode != vi_mode +#endif + ) || (( KEV.wVirtualKeyCode == VK_BACK + || KEV.wVirtualKeyCode == VK_TAB + || KEV.wVirtualKeyCode == VK_RETURN) + && (KST & 0x1f))) + /* Treat Esc (in emacs mode) and modified + Backspace/Tab/Enter as prefixed. */ + key = 0; + if (key || KEV.wVirtualKeyCode == '2') /* char 0, VK 2 -> C-@ */ + { + /* Ascii direct */ + pending_key = key; + pending_count = KEV.wRepeatCount; + if (pending_esc) + { + pending_count *= 2; + key = ESC; + } + } + else + /* Others prefixed */ + { + pending_prefix = EXT_PREFIX; + if (pending_esc) + pending_prefix |= 4; + if (KST & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) + pending_prefix |= 2; + if (KST & SHIFT_PRESSED) + pending_prefix |= 1; + pending_key = KEV.wVirtualKeyCode; + pending_count = KEV.wRepeatCount * 3; + key = ESC; + } + pending_count--; + return key; + } + break; + case MOUSE_EVENT: + if ((haveConsole & FOR_OUTPUT) && !rl_dispatching) + MouseEventProc (irec.Event.MouseEvent); + default: + break; + } + } + else + { + ReadFile (hStdin, &key, 1, &dummy, NULL); + if (dummy != 1) + return EOF; + if (key == '\r') + { + /* Ignore the CR in CRLF. */ + ReadFile (hStdin, &pending_key, 1, &dummy, NULL); + if (dummy == 1) + { + if (pending_key == '\n') + key = '\n'; + else + pending_count = 1; + } + } + return key; + } + } +} + +static void +MouseEventProc (MOUSE_EVENT_RECORD mev) +{ + static DWORD lastButtonState, cstat_flags; + static COORD src_down_pos; + static int src_linear_pos; + +#define RLPOS_CHANGED 1 + + switch (mev.dwEventFlags) + { + case 0: /* change in button state */ + + /* Cursor setting: + LEFT_BUTTON_PRESSED sets cursor anywhere on the screen, + thereafter, any change in button state will clip the cursor + position to the readline range if there has been no cursor + movement. Otherwise the cursor is reset to its old position. + */ + if (mev.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) + { + if (lastButtonState == 0) + { + src_down_pos = mev.dwMousePosition; + cstat_flags |= RLPOS_CHANGED; + SetConsoleCursorPosition (hStdout, mev.dwMousePosition); + + src_linear_pos = (int)src_down_pos.Y * _rl_screenwidth + + (int)src_down_pos.X; + if (src_linear_pos < rlScreenStart + rl_visible_prompt_length) + { + src_linear_pos = rlScreenStart + rl_visible_prompt_length; + src_down_pos.X = rlScreenOrigin.X + rl_visible_prompt_length; + src_down_pos.Y = rlScreenOrigin.Y; + } + if (src_linear_pos > rlScreenMax) + { + src_linear_pos = rlScreenMax; + src_down_pos = rlScreenEnd; + } + } + } + else + { + if (cstat_flags & RLPOS_CHANGED) + { + int linear_pos = (int)mev.dwMousePosition.Y * _rl_screenwidth + + (int)mev.dwMousePosition.X; + if (linear_pos < rlScreenStart + rl_visible_prompt_length) + { + linear_pos = rlScreenStart + rl_visible_prompt_length; + mev.dwMousePosition.X = rlScreenOrigin.X + rl_visible_prompt_length; + mev.dwMousePosition.Y = rlScreenOrigin.Y; + } + if (linear_pos > rlScreenMax) + { + linear_pos = rlScreenMax; + mev.dwMousePosition = rlScreenEnd; + } + if (*(PDWORD)&mev.dwMousePosition != *(PDWORD)&src_down_pos) + _rl_set_mark_at_pos (src_linear_pos - rlScreenStart - rl_visible_prompt_length); + rl_point = linear_pos - rlScreenStart - rl_visible_prompt_length; + _rl_last_c_pos = mev.dwMousePosition.X - rlScreenOrigin.X; + _rl_last_v_pos = mev.dwMousePosition.Y - rlScreenOrigin.Y; + } + SetConsoleCursorPosition (hStdout, mev.dwMousePosition); + cstat_flags &= ~RLPOS_CHANGED; + } + lastButtonState = mev.dwButtonState; + break; + case MOUSE_MOVED: /* the most frequent event */ + default: + break; + } +} +#endif /* !_WIN32 */ #if defined (HANDLE_MULTIBYTE) /* read multibyte char */ diff -urp readline-7-0/kill.c readline-7.0/kill.c --- readline-7-0/kill.c 2016-01-26 01:38:45 +1000 +++ readline-7.0/kill.c 2017-02-20 17:45:28 +1000 @@ -362,13 +362,13 @@ rl_unix_filename_rubout (count, key) while (count--) { c = rl_line_buffer[rl_point - 1]; - while (rl_point && (whitespace (c) || c == '/')) + while (rl_point && (whitespace (c) || _rl_is_path_sep (c))) { rl_point--; c = rl_line_buffer[rl_point - 1]; } - while (rl_point && (whitespace (c) == 0) && c != '/') + while (rl_point && (whitespace (c) == 0) && !_rl_is_path_sep (c)) { rl_point--; c = rl_line_buffer[rl_point - 1]; @@ -740,8 +740,9 @@ rl_bracketed_paste_begin (count, key) return (retval); } -/* A special paste command for Windows users.. */ +/* A special paste command for Windows users. */ #if defined (_WIN32) +#define WIN32_LEAN_AND_MEAN #include int diff -urp readline-7-0/parens.c readline-7.0/parens.c --- readline-7-0/parens.c 2016-01-26 01:39:10 +1000 +++ readline-7.0/parens.c 2017-02-19 21:35:29 +1000 @@ -40,6 +40,14 @@ #include "posixselect.h" +#if defined (_WIN32) +# define WIN32_LEAN_AND_MEAN +# include +# include "rldefs.h" +extern int haveConsole; +extern HANDLE hStdout, hStdin; +#endif + #if defined (HAVE_STRING_H) # include #else /* !HAVE_STRING_H */ @@ -140,7 +148,48 @@ rl_insert_close (count, invoking_key) (*rl_redisplay_function) (); ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); rl_point = orig_point; -#else /* !HAVE_SELECT */ +#elif defined (_WIN32) + int orig_point, match_point; + CONSOLE_SCREEN_BUFFER_INFO csbi; + WORD attr = 0, attri; + DWORD written; + + _rl_insert_char (1, invoking_key); + (*rl_redisplay_function) (); + match_point = + find_matching_open (rl_line_buffer, rl_point - 2, invoking_key); + + /* Emacs might message or ring the bell here, but I don't. */ + if (match_point < 0) + return 1; + + orig_point = rl_point; + rl_point = match_point; + (*rl_redisplay_function) (); + if ((haveConsole & FOR_OUTPUT) && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + ReadConsoleOutputAttribute (hStdout, &attr, 1, csbi.dwCursorPosition, &written); + attri = (attr & 0xFF00) | ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4); + WriteConsoleOutputAttribute (hStdout, &attri, 1, csbi.dwCursorPosition, &written); + } + if (haveConsole & FOR_INPUT) + { + DWORD start = GetTickCount (); + while (WaitForSingleObject (hStdin, _paren_blink_usec / 1000 + - (GetTickCount() - start)) == 0) + { + /* Ignore key release events. */ + INPUT_RECORD ir; + if (!PeekConsoleInput (hStdin, &ir, 1, &written) || written == 0 + || ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown) + break; + FlushConsoleInputBuffer (hStdin); + } + } + if (attr != 0) + WriteConsoleOutputAttribute (hStdout, &attr, 1, csbi.dwCursorPosition, &written); + rl_point = orig_point; +#else /* !_WIN32 */ _rl_insert_char (count, invoking_key); #endif /* !HAVE_SELECT */ } diff -urp readline-7-0/readline.c readline-7.0/readline.c --- readline-7-0/readline.c 2016-04-21 05:53:52 +1000 +++ readline-7.0/readline.c 2017-02-22 17:00:16 +1000 @@ -363,12 +363,12 @@ readline (prompt) RL_UNSETSTATE (RL_STATE_CALLBACK); #endif - rl_set_prompt (prompt); - rl_initialize (); if (rl_prep_term_function) (*rl_prep_term_function) (_rl_meta_flag); + rl_set_prompt (prompt); + #if defined (HANDLE_SIGNALS) rl_set_signals (); #endif @@ -1196,6 +1196,10 @@ readline_initialize_everything () /* Initialize the terminal interface. */ if (rl_terminal_name == 0) rl_terminal_name = sh_get_env_value ("TERM"); +#if defined (_WIN32) + if (rl_terminal_name == 0) + rl_terminal_name = "wincon"; +#endif _rl_init_terminal_io (rl_terminal_name); /* Bind tty characters to readline functions. */ @@ -1275,6 +1279,18 @@ bind_arrow_keys_internal (map) xkeymap = _rl_keymap; _rl_keymap = map; +#if defined (_WIN32) + rl_bind_keyseq_if_unbound ("\033\370&", rl_get_previous_history); + rl_bind_keyseq_if_unbound ("\033\370(", rl_get_next_history); + rl_bind_keyseq_if_unbound ("\033\370'", rl_forward_char); + rl_bind_keyseq_if_unbound ("\033\370%", rl_backward_char); + rl_bind_keyseq_if_unbound ("\033\372'", rl_forward_word); + rl_bind_keyseq_if_unbound ("\033\372%", rl_backward_word); + rl_bind_keyseq_if_unbound ("\033\370$", rl_beg_of_line); + rl_bind_keyseq_if_unbound ("\033\370#", rl_end_of_line); + rl_bind_keyseq_if_unbound ("\033\370.", rl_delete); + rl_bind_keyseq_if_unbound ("\033\370-", rl_overwrite_mode); +#else #if defined (__MSDOS__) rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history); rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char); @@ -1295,27 +1311,7 @@ bind_arrow_keys_internal (map) rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char); rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line); rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line); - -#if defined (__MINGW32__) - rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\340M", rl_forward_char); - rl_bind_keyseq_if_unbound ("\340K", rl_backward_char); - rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line); - rl_bind_keyseq_if_unbound ("\340S", rl_delete); - rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode); - - /* These may or may not work because of the embedded NUL. */ - rl_bind_keyseq_if_unbound ("\\000H", rl_get_previous_history); - rl_bind_keyseq_if_unbound ("\\000P", rl_get_next_history); - rl_bind_keyseq_if_unbound ("\\000M", rl_forward_char); - rl_bind_keyseq_if_unbound ("\\000K", rl_backward_char); - rl_bind_keyseq_if_unbound ("\\000G", rl_beg_of_line); - rl_bind_keyseq_if_unbound ("\\000O", rl_end_of_line); - rl_bind_keyseq_if_unbound ("\\000S", rl_delete); - rl_bind_keyseq_if_unbound ("\\000R", rl_overwrite_mode); -#endif +#endif /* _WIN32 */ _rl_keymap = xkeymap; } diff -urp readline-7-0/rlconf.h readline-7.0/rlconf.h --- readline-7-0/rlconf.h 2016-01-26 01:35:32 +1000 +++ readline-7.0/rlconf.h 2017-02-19 12:30:29 +1000 @@ -30,7 +30,7 @@ /* Define this to get support for colors when listing completions and in other places. */ -#define COLOR_SUPPORT +/* #define COLOR_SUPPORT */ /* This definition is needed by readline.c, rltty.c, and signals.c. */ /* If on, then readline handles signals in a way that doesn't suck. */ @@ -42,8 +42,12 @@ /* The next-to-last-ditch effort file name for a user-specific init file. */ #define DEFAULT_INPUTRC "~/.inputrc" -/* The ultimate last-ditch filenname for an init file -- system-wide. */ +/* The ultimate last-ditch filename for an init file -- system-wide. */ +#if !defined (_WIN32) #define SYS_INPUTRC "/etc/inputrc" +#else +#define SYS_INPUTRC "~~/inputrc" +#endif /* If defined, expand tabs to spaces. */ #define DISPLAY_TABS @@ -60,7 +64,7 @@ #define READLINE_CALLBACKS /* Define this if you want the cursor to indicate insert or overwrite mode. */ -/* #define CURSOR_MODE */ +#define CURSOR_MODE /* Define this if you want to enable code that talks to the Linux kernel tty auditing system. */ diff -urp readline-7-0/rldefs.h readline-7.0/rldefs.h --- readline-7-0/rldefs.h 2013-09-03 03:34:28 +1000 +++ readline-7.0/rldefs.h 2017-02-02 10:08:57 +1000 @@ -160,6 +160,15 @@ extern char *_rl_strpbrk PARAMS((const c # define SWAP(s, e) do { int t; t = s; s = e; e = t; } while (0) #endif +#if defined (_WIN32) +#define WAIT_FOR_INPUT 200 /* milliseconds to suspend maximally + when waiting for input */ +#define FOR_INPUT 1 /* flags for open state of the console */ +#define FOR_OUTPUT 2 +#define INITIALIZED 4 + +#endif /* _WIN32 */ + /* CONFIGURATION SECTION */ #include "rlconf.h" diff -urp readline-7-0/rlprivate.h readline-7.0/rlprivate.h --- readline-7-0/rlprivate.h 2016-01-26 01:35:48 +1000 +++ readline-7.0/rlprivate.h 2017-02-20 18:31:59 +1000 @@ -37,10 +37,14 @@ #define VI_COMMAND_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) #define VI_INSERT_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap) +#if defined (_WIN32) +#define RL_CHECK_SIGNALS() +#else #define RL_CHECK_SIGNALS() \ do { \ if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \ } while (0) +#endif #define RL_SIG_RECEIVED() (_rl_caught_signal != 0) #define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT) @@ -279,6 +283,15 @@ extern void _rl_clean_up_for_exit PARAMS extern void _rl_erase_entire_line PARAMS((void)); extern int _rl_current_display_line PARAMS((void)); +/* histexpand.c */ +#if defined (__MSDOS__) || defined (_WIN32) +extern char *_rl_last_path_sep PARAMS((const char *)); +#define _rl_is_path_sep(x) ((x) == '/' || (x) == '\\') +#else +#define _rl_last_path_sep(x) strrchr(x, '/') +#define _rl_is_path_sep(x) ((x) == '/') +#endif + /* input.c */ extern int _rl_any_typein PARAMS((void)); extern int _rl_input_available PARAMS((void)); @@ -470,6 +483,15 @@ extern int _rl_vi_ins_modestr_len; extern char *_rl_vi_cmd_mode_str; extern int _rl_vi_cmd_modestr_len; +/* histexpand.c */ +#if defined (__MSDOS__) || defined (_WIN32) +extern char _rl_path_sep_str[]; +#define _rl_path_sep_chr (*_rl_path_sep_str) +#else +#define _rl_path_sep_str "/" +#define _rl_path_sep_chr '/' +#endif + /* isearch.c */ extern char *_rl_isearch_terminators; diff -urp readline-7-0/rltty.c readline-7.0/rltty.c --- readline-7-0/rltty.c 2016-04-21 06:17:07 +1000 +++ readline-7.0/rltty.c 2017-02-20 22:22:39 +1000 @@ -26,6 +26,9 @@ # include #endif +/* for native Win32 environments this is hard stuff */ +#if !defined (_WIN32) + #include #include #include @@ -42,6 +45,11 @@ # include /* include for declaration of ioctl */ #endif +#else /* _WIN32 */ +#include "rldefs.h" +#include +#endif /* _WIN32 */ + #include "readline.h" #include "rlprivate.h" @@ -54,6 +62,7 @@ rl_voidfunc_t *rl_deprep_term_function = static void set_winsize PARAMS((int)); +#if !defined (_WIN32) /* **************************************************************** */ /* */ /* Saving and Restoring the TTY */ @@ -917,6 +926,115 @@ rltty_set_default_bindings (kmap) #endif } +#else /* _WIN32 */ + +/* **************************************************************** */ +/* */ +/* Default Key Bindings for Win32 Console */ +/* */ +/* **************************************************************** */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define CONSOLE_MODE ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT + +/* global vars used by other modules */ + +int haveConsole = 0; /* remember init result of the console */ +HANDLE hStdout, hStdin; /* these are different from stdin, stdout */ + +COORD rlScreenOrigin; /* readline origin in frame buffer coordinates */ +int rlScreenStart = 0; /* readline origin as frame screen buffer offset */ +COORD rlScreenEnd; /* end of line in frame buffer coordinates */ +int rlScreenMax = 0; /* end of line as linear frame buffer offset */ + +static DWORD savedConsoleMode = 0; /* to restore console on exit */ + +void +rltty_set_default_bindings (kmap) + Keymap kmap; +{ + rl_bind_keyseq_in_map ("\033\372.", rl_kill_word, kmap); + rl_bind_keyseq_in_map ("\033\371-", rl_paste_from_clipboard, kmap); + rl_bind_keyseq_in_map ("\033\371\b", rl_rubout, kmap); + rl_bind_keyseq_in_map ("\033\372\b", rl_backward_kill_word, kmap); + rl_bind_keyseq_in_map ("\\t", rl_menu_complete, kmap); + rl_bind_keyseq_in_map ("\033\371\t", rl_backward_menu_complete, kmap); + rl_bind_keyseq_in_map ("\033\370\33", rl_kill_full_line, kmap); + rl_bind_keyseq_in_map ("\033\372&", rl_history_search_backward, kmap); + rl_bind_keyseq_in_map ("\033\372(", rl_history_search_forward, kmap); + + /* Force creation of the keymaps for the remaining modifiers, to prevent + unassigned sequences inserting the virtual key (in emacs mode). */ + rl_bind_keyseq_in_map ("\033\373\\0", 0, kmap); /* Shift+Ctrl */ + rl_bind_keyseq_in_map ("\033\374\\0", 0, kmap); /* Alt */ + rl_bind_keyseq_in_map ("\033\375\\0", 0, kmap); /* Shift+Alt */ + rl_bind_keyseq_in_map ("\033\376\\0", 0, kmap); /* Ctrl+Alt */ + rl_bind_keyseq_in_map ("\033\377\\0", 0, kmap); /* Shift+Ctrl+Alt */ +} + +/* Query and set up a Windows Console */ + +void +rl_prep_terminal (meta_flag) + int meta_flag; +{ + _rl_echoing_p = 1; + + if (!(haveConsole & INITIALIZED)) + { + if (!(haveConsole & FOR_INPUT) + && ((hStdin = GetStdHandle (STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE)) + { + DWORD dummy; + INPUT_RECORD irec; + if (PeekConsoleInput (hStdin, &irec, 1, &dummy)) + { + haveConsole |= FOR_INPUT; + if (GetConsoleMode (hStdin, &savedConsoleMode)) + SetConsoleMode (hStdin, CONSOLE_MODE); + } + } + if ((hStdout = GetStdHandle (STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE) + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo (hStdout, &csbi) + && (csbi.dwSize.X > 0) && (csbi.dwSize.Y > 0)) + { + haveConsole |= FOR_OUTPUT; + rlScreenOrigin = csbi.dwCursorPosition; + rlScreenStart = (int)csbi.dwCursorPosition.Y * (int)csbi.dwSize.X + + (int)csbi.dwCursorPosition.X; + } + } + haveConsole |= INITIALIZED; + } +} + +/* Restore the console's normal settings and modes. */ +void +rl_deprep_terminal () +{ + SetConsoleMode (hStdin, savedConsoleMode); + haveConsole = 0; +} + +int +rl_restart_output (count, key) + int count, key; +{ + return 0; +} + +int +rl_stop_output (count, key) + int count, key; +{ + return 0; +} +#endif /* _WIN32 */ + /* New public way to set the system default editing chars to their readline equivalents. */ void @@ -926,6 +1044,7 @@ rl_tty_set_default_bindings (kmap) rltty_set_default_bindings (kmap); } +#if !defined (_WIN32) /* Rebind all of the tty special chars that readline worries about back to self-insert. Call this before saving the current terminal special chars with save_tty_chars(). This only works on POSIX termios or termio @@ -949,6 +1068,13 @@ rl_tty_unset_default_bindings (kmap) RESET_SPECIAL (_rl_tty_chars.t_werase); # endif /* VWERASE && TERMIOS_TTY_DRIVER */ } +#else +void +rl_tty_unset_default_bindings (kmap) + Keymap kmap; +{ +} +#endif /* _WIN32 */ #if defined (HANDLE_SIGNALS) diff -urp readline-7-0/shell.c readline-7.0/shell.c --- readline-7-0/shell.c 2013-03-14 00:17:00 +1000 +++ readline-7.0/shell.c 2017-02-02 10:08:57 +1000 @@ -187,6 +187,7 @@ sh_get_home_dir () # endif #endif +#if !defined (_WIN32) int sh_unset_nodelay_mode (fd) int fd; @@ -216,3 +217,4 @@ sh_unset_nodelay_mode (fd) return 0; } +#endif /* !_WIN32 */ diff -urp readline-7-0/signals.c readline-7.0/signals.c --- readline-7-0/signals.c 2016-08-26 22:28:51 +1000 +++ readline-7.0/signals.c 2017-02-14 09:33:22 +1000 @@ -78,9 +78,11 @@ typedef struct { SigHandler *sa_handler; # define SA_RESTART 0 #endif +#if !defined (_WIN32) static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *)); +#endif /* _WIN32 */ static RETSIGTYPE rl_signal_handler PARAMS((int)); static RETSIGTYPE _rl_handle_signal PARAMS((int)); @@ -111,8 +113,11 @@ int _rl_quit_char = 0; int _rl_susp_char = 0; static int signals_set_flag; +#ifdef SIGWINCH static int sigwinch_set_flag; +#endif +#if !defined (_WIN32) /* **************************************************************** */ /* */ /* Signal Handling */ @@ -551,6 +556,7 @@ rl_clear_signals () return 0; } +#endif /* !_WIN32 */ /* Clean up the terminal and readline state after catching a signal, before resending it to the calling application. */ @@ -598,6 +604,54 @@ rl_pending_signal () { return (_rl_caught_signal); } + +#if defined (_WIN32) + +#include +#include +#include + +/* Handling of CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_BREAK_EVENT, + * CTRL_LOGOFF_EVENT, CTRL_SHUTDOWN_EVENT, + * WINDOW_BUFFER_SIZE_EVENTs are handled separately see input.c + */ + +BOOL +CtrlEventHandler (DWORD dwEventType) +{ + if (dwEventType == CTRL_C_EVENT) + rl_free_line_state (); + rl_cleanup_after_signal (); + if (dwEventType == CTRL_C_EVENT) /* special treatment */ + { + if (rl_catch_signals == 1) /* > 1: handled only locally */ + { + raise (SIGINT); /* pass to program signal handler */ + rl_reset_after_signal (); /* on return go on */ + } + return TRUE; /* don't pass to upstream handlers */ + } + return FALSE; /* pass other events to handler chain */ +} + +int +rl_set_signals () +{ + if (rl_catch_signals && signals_set_flag == 0) + signals_set_flag = SetConsoleCtrlHandler ((PHANDLER_ROUTINE) CtrlEventHandler, TRUE); + return signals_set_flag; +} + +int +rl_clear_signals () +{ + if (signals_set_flag) + if (SetConsoleCtrlHandler ((PHANDLER_ROUTINE) CtrlEventHandler, FALSE)) + signals_set_flag = 0; + return signals_set_flag; +} + +#endif /* _WIN32 */ #endif /* HANDLE_SIGNALS */ /* **************************************************************** */ diff -urp readline-7-0/terminal.c readline-7.0/terminal.c --- readline-7-0/terminal.c 2016-01-26 01:36:21 +1000 +++ readline-7.0/terminal.c 2017-02-06 17:20:58 +1000 @@ -51,6 +51,14 @@ /* System-specific feature definitions and include files. */ #include "rldefs.h" +#if defined (_WIN32) +# include +extern int haveConsole; /* imported from rltty.c */ +extern HANDLE hStdout, hStdin; +extern COORD rlScreenEnd; +extern int rlScreenMax; +#endif /* _WIN32 */ + #ifdef __MSDOS__ # include #endif @@ -69,13 +77,6 @@ #include "rlshell.h" #include "xmalloc.h" -#if defined (__MINGW32__) -# include -# include - -static void _win_get_screensize PARAMS((int *, int *)); -#endif - #if defined (__EMX__) static void _emx_get_screensize PARAMS((int *, int *)); #endif @@ -95,7 +96,7 @@ int rl_change_environment = 1; /* */ /* **************************************************************** */ -#ifndef __MSDOS__ +#if !defined (__MSDOS__) && !defined (_WIN32) static char *term_buffer = (char *)NULL; static char *term_string_buffer = (char *)NULL; #endif @@ -202,30 +203,11 @@ _emx_get_screensize (swp, shp) } #endif -#if defined (__MINGW32__) -static void -_win_get_screensize (swp, shp) - int *swp, *shp; -{ - HANDLE hConOut; - CONSOLE_SCREEN_BUFFER_INFO scr; - - hConOut = GetStdHandle (STD_OUTPUT_HANDLE); - if (hConOut != INVALID_HANDLE_VALUE) - { - if (GetConsoleScreenBufferInfo (hConOut, &scr)) - { - *swp = scr.dwSize.X; - *shp = scr.srWindow.Bottom - scr.srWindow.Top + 1; - } - } -} -#endif - /* Get readline's idea of the screen size. TTY is a file descriptor open to the terminal. If IGNORE_ENV is true, we do not pay attention to the values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being non-null serve to check whether or not we have initialized termcap. */ +#if !defined (_WIN32) void _rl_get_screen_size (tty, ignore_env) int tty, ignore_env; @@ -317,6 +299,30 @@ _rl_get_screen_size (tty, ignore_env) _rl_screenchars = _rl_screenwidth * _rl_screenheight; } +#else /* _WIN32*/ + +void +_rl_get_screen_size (tty, ignore_env) + int tty, ignore_env; +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + /* This occurs before prep, so haveConsole is not yet initialized. */ + if (/*(haveConsole & FOR_OUTPUT) &&*/ + GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi)) + { + _rl_screenwidth = csbi.dwSize.X; + _rl_screenheight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + } + else + { + _rl_screenwidth = 80; + _rl_screenheight = 24; + } + _rl_screenchars = _rl_screenwidth * _rl_screenheight; +} +#endif /* _WIN32 */ + void _rl_set_screen_size (rows, cols) int rows, cols; @@ -379,6 +385,7 @@ rl_resize_terminal () } } +#if !defined (_WIN32) struct _tc_string { const char * const tc_var; char **tc_value; @@ -435,11 +442,37 @@ get_term_capabilities (bp) #endif tcap_initialized = 1; } +#endif /* !_WIN32 */ int _rl_init_terminal_io (terminal_name) const char *terminal_name; { +#if defined (_WIN32) + _rl_term_cr = "\r"; /* any value != 0 */ + _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; /* !! we emulate insertion */ + _rl_term_up = "y"; /* any value != 0 */ + _rl_term_dc = _rl_term_DC = (char *)NULL; /* !! we emulate deletion */ + _rl_visible_bell = "\a"; + + _rl_get_screen_size (0, 1); + + /* Let Windows handle meta keys! */ + term_has_meta = 0; + _rl_term_mm = _rl_term_mo = (char *)NULL; + + /* It probably has arrow keys, but I don't know what they are. */ + _rl_term_ku = _rl_term_kd = _rl_term_kr = _rl_term_kl = (char *)NULL; + +#if defined (HACK_TERMCAP_MOTION) + _rl_term_forward_char = (char *)NULL; +#endif /* HACK_TERMCAP_MOTION */ + + _rl_terminal_can_insert = 0; + _rl_term_autowrap = 1; + +#else /* !_WIN32 */ + const char *term; char *buffer; int tty, tgetent_ret; @@ -579,9 +612,12 @@ _rl_init_terminal_io (terminal_name) bind_termcap_arrow_keys (vi_insertion_keymap); #endif /* VI_MODE */ +#endif /* !_WIN32 */ + return 0; } +#if !defined (_WIN32) /* Bind the arrow key sequences from the termcap description in MAP. */ static void bind_termcap_arrow_keys (map) @@ -620,6 +656,7 @@ rl_get_termcap (cap) } return ((char *)NULL); } +#endif /* !_WIN32 */ /* Re-initialize the terminal considering that the TERM/TERMCAP variable has changed. */ @@ -632,6 +669,7 @@ rl_reset_terminal (terminal_name) return 0; } +#if !defined (_WIN32) /* A function for the use of tputs () */ #ifdef _MINIX void @@ -688,6 +726,76 @@ rl_crlf () return 0; } +#else /* _WIN32 */ + +/* Write COUNT characters from STRING to the output stream. */ +void +_rl_output_some_chars (string, count) + const char *string; + int count; +{ + /* This used to do more; perhaps it may again. */ + CONSOLE_SCREEN_BUFFER_INFO csbi; + fwrite (string, 1, count, _rl_out_stream); + if ((haveConsole & FOR_OUTPUT) && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + int linear_pos = (int)csbi.dwCursorPosition.Y * (int)csbi.dwSize.X + + (int)csbi.dwCursorPosition.X; + if (linear_pos > rlScreenMax) + { + rlScreenEnd = csbi.dwCursorPosition; + rlScreenMax = linear_pos; + } + } +} + +/* This is used to collect all putc output */ +int +_rl_output_character_function (c) + int c; +{ +#if 0 + _rl_output_some_chars ((char *)&c, 1); + return 1; +#else + return putc (c, _rl_out_stream); +#endif +} + +/* Move the cursor back. */ +int +_rl_backspace (count) + int count; +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + if ((haveConsole & FOR_OUTPUT) && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + while (count > csbi.dwCursorPosition.X) + { + --csbi.dwCursorPosition.Y; + count -= csbi.dwCursorPosition.X + 1; + csbi.dwCursorPosition.X = csbi.dwSize.X - 1; + } + csbi.dwCursorPosition.X -= count; + SetConsoleCursorPosition (hStdout, csbi.dwCursorPosition); + } + return 0; +} + +/* Move to the start of the next line. */ +int +rl_crlf () +{ +#if 0 + _rl_output_some_chars ("\n", 1); +#else + putc ('\n', _rl_out_stream); +#endif + return 0; +} +#endif /* _WIN32 */ + /* Ring the terminal bell. */ int rl_ding () @@ -702,8 +810,20 @@ rl_ding () case VISIBLE_BELL: if (_rl_visible_bell) { -#ifdef __DJGPP__ +#if defined (__DJGPP__) ScreenVisualBell (); +#elif defined (_WIN32) + CONSOLE_SCREEN_BUFFER_INFO csbi; + if ((haveConsole & FOR_OUTPUT) && GetConsoleScreenBufferInfo (hStdout, &csbi)) + { + WORD attr, attri; + DWORD written; + ReadConsoleOutputAttribute (hStdout, &attr, 1, csbi.dwCursorPosition, &written); + attri = (attr & 0xFF00) | ((attr & 0x0F) << 4) | ((attr & 0xF0) >> 4); + WriteConsoleOutputAttribute (hStdout, &attri, 1, csbi.dwCursorPosition, &written); + Sleep (100); + WriteConsoleOutputAttribute (hStdout, &attr, 1, csbi.dwCursorPosition, &written); + } #else tputs (_rl_visible_bell, 1, _rl_output_character_function); #endif @@ -711,8 +831,12 @@ rl_ding () } /* FALLTHROUGH */ case AUDIBLE_BELL: +#if defined (_WIN32) + MessageBeep (MB_OK); +#else fprintf (stderr, "\007"); fflush (stderr); +#endif break; } return (0); @@ -731,7 +855,7 @@ static int enabled_meta = 0; /* flag ind void _rl_enable_meta_key () { -#if !defined (__DJGPP__) +#if !defined (__DJGPP__) && !defined (_WIN32) if (term_has_meta && _rl_term_mm) { tputs (_rl_term_mm, 1, _rl_output_character_function); @@ -743,7 +867,7 @@ _rl_enable_meta_key () void _rl_disable_meta_key () { -#if !defined (__DJGPP__) +#if !defined (__DJGPP__) && !defined (_WIN32) if (term_has_meta && _rl_term_mo && enabled_meta) { tputs (_rl_term_mo, 1, _rl_output_character_function); @@ -756,7 +880,7 @@ void _rl_control_keypad (on) int on; { -#if !defined (__DJGPP__) +#if !defined (__DJGPP__) && !defined (_WIN32) if (on && _rl_term_ks) tputs (_rl_term_ks, 1, _rl_output_character_function); else if (!on && _rl_term_ke) @@ -778,7 +902,23 @@ void _rl_set_cursor (im, force) int im, force; { -#ifndef __MSDOS__ +#if defined (_WIN32) + CONSOLE_CURSOR_INFO cci; + static DWORD cursor_size; + if (haveConsole && GetConsoleCursorInfo (hStdout, &cci)) + { + if (cursor_size == 0) + cursor_size = cci.dwSize; + if (force || im != rl_insert_mode) + { + if (im == RL_IM_OVERWRITE) + cci.dwSize = (cursor_size >= 50 ? 25 : 100); + else + cci.dwSize = cursor_size; + SetConsoleCursorInfo (hStdout, &cci); + } + } +#elif !defined (__MSDOS__) if (_rl_term_ve && _rl_term_vs) { if (force || im != rl_insert_mode) diff -urp readline-7-0/text.c readline-7.0/text.c --- readline-7-0/text.c 2016-02-16 06:06:58 +1000 +++ readline-7.0/text.c 2017-02-20 11:13:47 +1000 @@ -999,7 +999,14 @@ rl_quoted_insert (count, key) return (0); } #endif - + + if (count < 0) + { + int r; + do r = _rl_insert_next (1); while (!r && ++count != 0); + return r; + } + return _rl_insert_next (count); } diff -urp readline-7-0/tilde.c readline-7.0/tilde.c --- readline-7-0/tilde.c 2016-04-28 22:17:50 +1000 +++ readline-7.0/tilde.c 2017-02-20 22:35:56 +1000 @@ -171,7 +171,7 @@ tilde_find_suffix (string) for (i = 0; i < string_len; i++) { -#if defined (__MSDOS__) +#if defined (__MSDOS__) || defined (_WIN32) if (string[i] == '/' || string[i] == '\\' /* || !string[i] */) #else if (string[i] == '/' /* || !string[i] */) @@ -275,7 +275,7 @@ isolate_tilde_prefix (fname, lenp) int i; ret = (char *)xmalloc (strlen (fname)); -#if defined (__MSDOS__) +#if defined (__MSDOS__) || defined (_WIN32) for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) #else for (i = 1; fname[i] && fname[i] != '/'; i++) @@ -377,6 +377,21 @@ tilde_expand_word (filename) return (glue_prefix_and_suffix (expansion, filename, 1)); } +#if defined (_WIN32) + /* A leading `~~/' or a bare `~~' is translated to all users. */ + if (filename[1] == '~' && (filename[2] == '\0' || filename[2] == '/')) + { + /* Prefix %ALLUSERSPROFILE% to the rest of the string. */ + expansion = sh_get_env_value ("ALLUSERSPROFILE"); + + /* If there is no ALLUSERSPROFILE variable, use the current user. */ + if (expansion == 0) + expansion = sh_get_home_dir (); + + return (glue_prefix_and_suffix (expansion, filename, 2)); + } +#endif + username = isolate_tilde_prefix (filename, &user_len); if (tilde_expansion_preexpansion_hook) diff -urp readline-7-0/vi_mode.c readline-7.0/vi_mode.c --- readline-7-0/vi_mode.c 2016-02-29 05:36:14 +1000 +++ readline-7.0/vi_mode.c 2017-02-06 18:41:29 +1000 @@ -594,7 +594,8 @@ rl_vi_bword (count, ignore) so we will go back to the start of the previous word. */ if (!whitespace (rl_line_buffer[rl_point]) && whitespace (rl_line_buffer[rl_point - 1])) - rl_point--; + if (--rl_point == 0) + break; /* If this character and the previous character are `opposite', move back so we don't get messed up by the rl_point++ down there in