It always annoyed me that the Info reader doesn't work on MS-Windows, because no one wrote the code for screen output and keyboard input for that platform. So I finally did it myself.
The set of patches below are mainly for this issue, but they also solve a compiler warning in building makeinfo and fix a crash in man.c for !PIPE_USE_FORK platforms. Let me know if something here is unclear or needs more changes. Thanks. 2012-01-17 Eli Zaretskii <[email protected]> Support for MS-Windows screen and keyboard in Info. * system.h (SET_SCREEN_SIZE_HELPER) [__MINGW32__]: Define. * info/tilde.c (tilde_expand_word) [__MINGW32__]: Don't call getpwuid or getpwnam; instead, consider "." as "home" if HOME is not set in the environment. Support tilde_expansion_failure_hook. * info/terminal.c [_WIN32]: Include pcterm.h. (terminal_initialize_terminal) [__MINGW32__]: Don't access `ospeed'. (terminal_prep_terminal, terminal_unprep_terminal) [__MINGW32__]: Ifdef away the TIOC code for Windows. * info/termdep.h [__MINGW32__]: Don't include sgtty.h. [_WIN32]: Add a prototype for `sleep'. * info/signals.c (redisplay_after_signal) (reset_info_window_sizes): Make these 2 functions extern from static, as they are called on MS-Windows from other files. * info/session.c (read) [__MINGW32__]: Redirect read and _read to w32_read. (info_gather_typeahead) [__MINGW32__]: Call w32_chars_avail to find out how many typeahead is available. * info/pcterm.c <struct text_info, struct termios> [_WIN32]: Definitions for the MS-Windows build. (w32_info_prep, w32_info_unprep, w32_cleanup, w32_info_init) (gettextinfo, textattr, textmode, ScreenGetCursor) (ScreenSetCursor, ScreenClear, clreol, ScreenVisualBell) (movetext, ScreenRows, ScreenCols, _set_screen_lines) (w32_set_screen_dimensions) [_WIN32]: New; screen output and cursor control functions for MS-Windows. (sleep, w32_our_tty, define_seq, w32keyseq, w32_kbd_read) (w32_chars_avail, w32_read) [_WIN32]: New; keyboard input functions and their subroutines for MS-Windows. (pc_prep_terminal) [_WIN32]: Call w32_info_prep. (pc_unprep_terminal) [_WIN32]: Call w32_info_unprep. Restore the screen buffer size to what we found on startup. (pc_initialize_terminal) [_WIN32]: Let term_name be "w32console". Condition MSDOS key definitions on __MSDOS__. (kill) [_WIN32]: Don't clear the screen and don't write "stopped" message on MS-Windows. Special suspend code for MS-Windows. * info/man.c [__MINGW32__]: Don't include sys/ioctl.h. Fix a crash in vewing man pages. * info/man.c (get_manpage_contents) [!PIPE_USE_FORK]: Fix a crasher due to addition of "-a" to the man command line arguments. Miscellaneous MS-Windows related fixes. * info/infokey.c (main): On MS-Windows, consider the current directory a "home" if HOME is not defined in the environment. * info/infomap.c (fetch_user_maps): Likewise. * info/info.c <option long_options>: Enable the speech-friendly options on MS-Windows as well. (main): Likewise. * info/dir.c (new_dir_file_p): Don't optimize the test for a new file when the inode is zero (MS-Windows). * makeinfo/index.c: Add a prototype for mbscasecmp. diff -ubBwp -r texinfo-4.13.orig/system.h texinfo-4.13/system.h --- texinfo-4.13.orig/system.h 2008-07-27 02:54:54.000000000 +0300 +++ texinfo-4.13/system.h 2011-08-10 09:10:17.212615400 +0300 @@ -184,6 +184,9 @@ extern int strcoll (); # define NULL_DEVICE "/dev/null" # define PIPE_USE_FORK 1 # else /* O_BINARY && !__CYGWIN__ */ +# ifdef __MINGW32__ +# define SET_SCREEN_SIZE_HELPER terminal_prep_terminal() +# endif /* _WIN32 */ # define DEFAULT_TMPDIR "c:/" # define PATH_SEP ";" # define STRIP_DOT_EXE 1 diff -ubBwp -r texinfo-4.13.orig/info/dir.c texinfo-4.13/info/dir.c --- texinfo-4.13.orig/info/dir.c 2008-06-12 16:39:20.000000000 +0300 +++ texinfo-4.13/info/dir.c 2011-11-02 12:32:10.970269800 +0200 @@ -40,7 +40,7 @@ static char *dirs_to_add[] = { /* Return zero if the file represented in the stat structure TEST has - already been seen, nonzero else. */ + already been seen, nonzero otherwise. */ typedef struct { @@ -59,7 +59,10 @@ new_dir_file_p (struct stat *test) { dir_file_list_entry_type entry; entry = dir_file_list[i]; - if (entry.device == test->st_dev && entry.inode == test->st_ino) + if (entry.device == test->st_dev && entry.inode == test->st_ino + /* On MS-Windows, `stat' returns zero as the inode, so we + effectively disable this optimization for that OS. */ + && entry.inode != 0) return 0; } diff -ubBwp -r texinfo-4.13.orig/info/info.c texinfo-4.13/info/info.c --- texinfo-4.13.orig/info/info.c 2008-08-16 03:17:04.000000000 +0300 +++ texinfo-4.13/info/info.c 2011-08-09 13:33:09.627126400 +0300 @@ -82,7 +82,7 @@ int raw_escapes_p = 1; /* Non-zero means print the absolute location of the file to be loaded. */ static int print_where_p = 0; -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) /* Non-zero indicates that screen output should be made 'speech-friendly'. Since on MSDOS the usual behavior is to write directly to the video memory, speech synthesizer software cannot grab the output. Therefore, @@ -118,14 +118,14 @@ static struct option long_options[] = { { "version", 0, &print_version_p, 1 }, { "vi-keys", 0, &vi_keys_p, 1 }, { "where", 0, &print_where_p, 1 }, -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) { "speech-friendly", 0, &speech_friendly, 1 }, #endif {NULL, 0, NULL, 0} }; /* String describing the shorthand versions of the long options found above. */ -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) static char *short_options = "k:d:n:f:ho:ORswb"; #else static char *short_options = "k:d:n:f:ho:ORws"; @@ -239,12 +239,12 @@ main (int argc, char *argv[]) print_where_p = 1; break; -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) /* User wants speech-friendly output. */ case 'b': speech_friendly = 1; break; -#endif /* __MSDOS__ */ +#endif /* __MSDOS__ || __MINGW32__ */ /* User has specified a string to search all indices for. */ case 'k': @@ -622,7 +622,7 @@ Options:\n\ --restore=FILENAME read initial keystrokes from FILENAME.\n\ -O, --show-options, --usage go to command-line options node.")); -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) puts (_("\ -b, --speech-friendly be friendly to speech synthesizers.")); #endif diff -ubBwp -r texinfo-4.13.orig/info/infokey.c texinfo-4.13/info/infokey.c --- texinfo-4.13.orig/info/infokey.c 2008-06-12 16:39:20.000000000 +0300 +++ texinfo-4.13/info/infokey.c 2011-08-09 13:33:56.674001400 +0300 @@ -178,7 +178,7 @@ There is NO WARRANTY, to the extent perm char *homedir; homedir = getenv ("HOME"); -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) if (!homedir) homedir = "."; #endif diff -ubBwp -r texinfo-4.13.orig/info/infomap.c texinfo-4.13/info/infomap.c --- texinfo-4.13.orig/info/infomap.c 2008-06-12 16:39:21.000000000 +0300 +++ texinfo-4.13/info/infomap.c 2011-08-30 15:17:48.860949700 +0300 @@ -928,7 +928,7 @@ fetch_user_maps (void) strcat(filename, "/"); strcat(filename, INFOKEY_FILE); } -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) /* Poor baby, she doesn't have a HOME... */ else filename = xstrdup(INFOKEY_FILE); /* try current directory */ diff -ubBwp -r texinfo-4.13.orig/info/man.c texinfo-4.13/info/man.c --- texinfo-4.13.orig/info/man.c 2008-07-06 03:32:19.000000000 +0300 +++ texinfo-4.13/info/man.c 2011-07-25 15:15:38.299328900 +0300 @@ -20,7 +20,9 @@ Originally written by Brian Fox Thu May 4 09:17:52 1995. */ #include "info.h" +#ifndef __MINGW32__ #include <sys/ioctl.h> +#endif #include "signals.h" #if defined (HAVE_SYS_TIME_H) #include <sys/time.h> diff -ubBwp -r texinfo-4.13.orig/info/pcterm.c texinfo-4.13/info/pcterm.c --- texinfo-4.13.orig/info/pcterm.c 2008-06-12 16:39:21.000000000 +0300 +++ texinfo-4.13/info/pcterm.c 2011-11-02 12:04:45.126519800 +0200 @@ -18,10 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* WARNING WARNING WARNING!!! - This probably won't work as is with anything but DJGPP! However, Borland - should come close, and other PC compilers will need minor modifications. */ +/* WARNING WARNING WARNING!!! This probably won't work as is with + anything but DJGPP and MinGW! However, Borland should come close, + and other PC compilers will need minor modifications. */ +#ifdef __MSDOS__ /* intl/libintl.h defines a macro `gettext' which conflicts with conio.h header. */ #ifdef gettext @@ -32,6 +33,42 @@ #include <pc.h> #include <keys.h> #include <conio.h> +#endif + +#ifdef _WIN32 +#include <io.h> +#include <conio.h> +#include <process.h> +#include <windows.h> + +struct text_info { + WORD normattr; + WORD attribute; + SHORT winleft; + SHORT wintop; + SHORT winright; + SHORT winbottom; + SHORT screenheight; + SHORT screenwidth; + SHORT curx; + SHORT cury; + COORD bufsize; + unsigned char currmode; /* unused and unsupported for Windows */ +}; + +struct termios { + int dummy; +}; + +enum text_modes { LASTMODE=-1 }; + +#define cprintf _cprintf +#define cputs _cputs + +#undef read +#undef _read + +#endif #include "variables.h" @@ -44,10 +81,515 @@ extern int speech_friendly; /* defined i /* **************************************************************** */ static struct text_info outside_info; /* holds screen params outside Info */ +#ifdef _WIN32 +static SHORT norm_attr, inv_attr; +static SHORT current_attr; +static HANDLE hstdin = INVALID_HANDLE_VALUE; +static HANDLE hstdout = INVALID_HANDLE_VALUE; +static HANDLE hinfo = INVALID_HANDLE_VALUE; +static HANDLE hscreen = INVALID_HANDLE_VALUE; +static DWORD old_inpmode; +#else static unsigned char norm_attr, inv_attr; +#endif static unsigned const char * find_sequence (int); +#ifdef _WIN32 + +/* Windows-specific initialization and de-initialization. */ +void +w32_info_prep (void) +{ + SetConsoleActiveScreenBuffer (hinfo); + current_attr = norm_attr; + hscreen = hinfo; + SetConsoleMode (hstdin, ENABLE_WINDOW_INPUT); +} + +void +w32_info_unprep (void) +{ + SetConsoleActiveScreenBuffer (hstdout); + current_attr = outside_info.normattr; + hscreen = hstdout; + SetConsoleMode (hstdin, old_inpmode); +} + +void +w32_cleanup (void) +{ + CloseHandle (hinfo); +} + +static void w32_info_init (void) __attribute__((constructor)); + +static void +w32_info_init (void) +{ + static void pc_initialize_terminal (char *); + + /* We need to set this single hook here; the rest + will be set by pc_initialize_terminal when it is called. */ + terminal_initialize_terminal_hook = pc_initialize_terminal; +} + +/* Emulate DJGPP conio functions for Windows. */ +static void +gettextinfo (struct text_info *ti) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + static TCHAR errbuf[500]; + + hstdin = GetStdHandle (STD_INPUT_HANDLE); + hstdout = GetStdHandle (STD_OUTPUT_HANDLE); + hinfo = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CONSOLE_TEXTMODE_BUFFER, NULL); + + if (hstdin != INVALID_HANDLE_VALUE + && hstdout != INVALID_HANDLE_VALUE + && hinfo != INVALID_HANDLE_VALUE + && GetConsoleMode (hstdin, &old_inpmode) + && GetConsoleScreenBufferInfo (hstdout, &csbi)) + { + ti->normattr = csbi.wAttributes; + ti->winleft = 1; + ti->wintop = 1; + ti->winright = csbi.srWindow.Right + 1; + ti->winbottom = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + ti->attribute = csbi.wAttributes; + ti->screenheight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + ti->screenwidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; + ti->curx = csbi.dwCursorPosition.X; + ti->cury = csbi.dwCursorPosition.Y; + ti->bufsize = csbi.dwSize; + + atexit (w32_cleanup); + } + else + { + DWORD error_no = GetLastError (); + + if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, + error_no, + 0, /* choose most suitable language */ + errbuf, sizeof (errbuf), NULL)) + sprintf (errbuf, "w32 error %u", error_no); + CloseHandle (hinfo); + info_error (_("Terminal cannot be initialized: %s\n"), errbuf, NULL); + xexit (1); + } +} + +void +textattr (int attr) +{ + SetConsoleTextAttribute (hscreen, attr); +} + +void +textmode (int mode) +{ + /* Nothing. */ +} + +void +ScreenGetCursor (int *row, int *col) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + *row = csbi.dwCursorPosition.Y; + *col = csbi.dwCursorPosition.X; +} + +void +ScreenSetCursor (int row, int col) +{ + COORD cursor_pos; + + cursor_pos.X = col; + cursor_pos.Y = row; + + SetConsoleCursorPosition (hscreen, cursor_pos); +} + +void +ScreenClear (void) +{ + DWORD nchars = screenwidth * screenheight; + COORD start_pos; + DWORD written; + + start_pos.X = start_pos.Y = 0; + FillConsoleOutputAttribute (hscreen, norm_attr, nchars, start_pos, &written); + FillConsoleOutputCharacter (hscreen, ' ', nchars, start_pos, &written); +} + +void +clreol (void) +{ + DWORD nchars; + COORD start_pos; + DWORD written; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + start_pos = csbi.dwCursorPosition; + nchars = csbi.dwSize.X - start_pos.X; + + FillConsoleOutputAttribute (hscreen, current_attr, nchars, start_pos, + &written); + FillConsoleOutputCharacter (hscreen, ' ', nchars, start_pos, &written); +} + +void +ScreenVisualBell (void) +{ + DWORD nchars = screenwidth * screenheight; + COORD start_pos; + DWORD written; + + start_pos.X = start_pos.Y = 0; + FillConsoleOutputAttribute (hscreen, inv_attr, nchars, start_pos, &written); + Sleep (20); + FillConsoleOutputAttribute (hscreen, norm_attr, nchars, start_pos, &written); +} + +int +movetext(int left, int top, int right, int bottom, int destleft, int desttop) +{ + SMALL_RECT src; + COORD dest; + CHAR_INFO fill; + + src.Left = left - 1; + src.Top = top - 1; + src.Right = right - 1; + src.Bottom = bottom - 1; + + dest.X = destleft - 1; + dest.Y = desttop - 1; + + fill.Attributes = norm_attr; + fill.Char.AsciiChar = (CHAR)' '; + + return ScrollConsoleScreenBuffer (hscreen, &src , NULL, dest, &fill) != 0; +} + +int +ScreenRows (void) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + return csbi.srWindow.Bottom - csbi.srWindow.Top + 1; +} + +int +ScreenCols (void) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + return csbi.srWindow.Right - csbi.srWindow.Left + 1; +} + +void +_set_screen_lines (int lines) +{ + SMALL_RECT window_rectangle; + CONSOLE_SCREEN_BUFFER_INFO csbi; + COORD scrbufsize; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + + window_rectangle = csbi.srWindow; + window_rectangle.Bottom = window_rectangle.Top + lines - 1; + SetConsoleWindowInfo (hscreen, TRUE, &window_rectangle); + + /* Set the screen buffer size to the same dimensions as the window, + so that the dysfunctional scroll bar disappears. */ + scrbufsize.X = window_rectangle.Right - window_rectangle.Left + 1; + scrbufsize.Y = window_rectangle.Bottom - window_rectangle.Top + 1; + SetConsoleScreenBufferSize (hscreen, scrbufsize); +} + +void +w32_set_screen_dimensions (int cols, int rows) +{ + SMALL_RECT window_rectangle; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo (hscreen, &csbi); + + window_rectangle = csbi.srWindow; + window_rectangle.Bottom = window_rectangle.Top + rows - 1; + window_rectangle.Right = window_rectangle.Left + cols - 1; + SetConsoleWindowInfo (hscreen, TRUE, &window_rectangle); +} + +/* Emulate `sleep'. */ +unsigned +sleep (unsigned sec) +{ + Sleep (sec*1000); + return 0; +} + +/* Keyboard input support. */ + +static int +w32_our_tty (int fd) +{ + return + isatty (fd) + /* Windows `isatty' actually tests for character devices, so the + null device gets reported as a tty. Fix that by calling + `lseek'. */ + && lseek (fd, SEEK_CUR, 0) == -1 + /* Is this our tty? */ + && hstdin != INVALID_HANDLE_VALUE + && hstdin == (HANDLE)_get_osfhandle (fd); +} + +/* Translate a Windows key event into the equivalent sequence of bytes + to be submitted to Info dispatcher. */ +#define define_seq(p,s1,s2) \ + do { \ + if ((ctl & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) \ + memcpy (p, s1, sizeof (s1)), p += sizeof (s1) - 1; \ + else \ + memcpy (p, s2, sizeof (s2)), p += sizeof (s2) - 1; \ + } while (0) + +static int +w32keyseq (unsigned char ascii_ch, WORD vkey, DWORD ctl, unsigned char *seq) +{ + unsigned char *p = seq; + + switch (ascii_ch) + { + case '\0': + /* Keys with no ASCII code are extended keys, like arrows. */ + switch (vkey) + { + case VK_PRIOR: + define_seq (p, "\033\061p", "\033v"); + break; + case VK_NEXT: + define_seq (p, "\033\061n", "\026"); + break; + case VK_END: + define_seq (p, "\033>", "\033>"); + break; + case VK_HOME: + define_seq (p, "\033<", "\033<"); + break; + case VK_LEFT: + define_seq (p, "\033b", "\033[D"); + break; + case VK_UP: + define_seq (p, "\033\061u", "\033[A"); + break; + case VK_RIGHT: + define_seq (p, "\033f", "\033[C"); + break; + case VK_DOWN: + define_seq (p, "\033\061m", "\033[B"); + break; + case VK_INSERT: + define_seq (p, "\033[L", "\033[L"); + break; + case VK_DELETE: /* Delete => Ctrl-d, Alt-Delete => ESC d */ + if ((ctl & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0) + define_seq (p, "\033d", "\033d"); + else + define_seq (p, "\033d", "\004"); + break; + case VK_HELP: /* F1 => Ctrl-h */ + case VK_F1: + *p++ = '\010'; + break; + case 50: /* Ctrl-@ => '\0' */ + if ((ctl & SHIFT_PRESSED) != 0) + *p++ = '\0'; + break; + default: + if (0x41 <= vkey && vkey <= 0x5a) + { + /* Alt-Ctrl-a, Alt-Ctrl-b, etc. */ + *p++ = '\033'; + *p++ = '\001' + vkey - 0x41; + } + } + break; + case ' ': /* Ctrl-SPC => '\0' */ + if ((ctl & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) + ascii_ch = '\0'; + *p++ = ascii_ch; + break; + case '\t': /* Shift-TAB/Alt-TAB => Esc-TAB */ + if ((ctl & (SHIFT_PRESSED | LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0) + { + memcpy (p, "\033\011", sizeof ("\033\011")); + p += sizeof ("\033\011") - 1; + } + else + *p++ = '\t'; + break; + case '\b': + /* Backspace => DEL. */ + ascii_ch = '\177'; + /* FALLTHROUGH */ + default: + if ((ctl & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0) + *p++ = '\033'; + *p++ = ascii_ch; + break; + } + return p - seq; +} + +static unsigned char buffered_chars[512]; +static size_t buf_head; +static size_t buf_tail; + +static ssize_t +w32_kbd_read (unsigned char *inbuf, size_t n) +{ + DWORD nevents, nread; + INPUT_RECORD inrec; + ssize_t nret = 0; + + do { + + /* Stuff any unread buffered characters. */ + while (buf_head < buf_tail && n > 0) + { + *inbuf++ = buffered_chars[buf_head++]; + nret++; + n--; + } + if (n <= 0) + break; + + /* Wait for input. */ + while (GetNumberOfConsoleInputEvents (hstdin, &nevents) + && nevents < 1) + Sleep (20); + + while (nevents-- && n > 0) + { + if (!ReadConsoleInput (hstdin, &inrec, 1, &nread)) + return -1; + + if (nread > 0) + { + switch (inrec.EventType) + { + case KEY_EVENT: + if (inrec.Event.KeyEvent.bKeyDown == TRUE + && !(inrec.Event.KeyEvent.wVirtualScanCode == 0 + || inrec.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT + || inrec.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL + || inrec.Event.KeyEvent.wVirtualKeyCode == VK_MENU)) + { + unsigned char keyseq[10]; + int count = inrec.Event.KeyEvent.wRepeatCount; + unsigned char ch = inrec.Event.KeyEvent.uChar.AsciiChar; + WORD vkey = inrec.Event.KeyEvent.wVirtualKeyCode; + DWORD ctl_state = inrec.Event.KeyEvent.dwControlKeyState; + int nbytes = w32keyseq (ch, vkey, ctl_state, keyseq); + + /* Supply up to N characters to the caller. */ + while (count && n >= nbytes) + { + if (nbytes == 1 && keyseq[0] == '\032') + { + terminal_goto_xy (0, screenheight - 1); + terminal_clear_to_eol (); + fflush (stdout); + terminal_unprep_terminal (); + kill (getpid (), 0); + terminal_prep_terminal (); + reset_info_window_sizes (); + } + else + { + memcpy (&inbuf[nret], keyseq, nbytes); + nret += nbytes; + n -= nbytes; + } + count--; + } + /* Buffer the rest. */ + if (count > 0) + { + buf_head = buf_tail = 0; + while (count-- + && buf_tail < sizeof(buffered_chars) - nbytes) + { + memcpy (&buffered_chars[buf_tail], keyseq, nbytes); + buf_tail += nbytes; + } + } + } + break; + case WINDOW_BUFFER_SIZE_EVENT: + { + int rows, cols; + + /* Note: this event is only sent when the console + window's _screen_buffer_ size is changed via + the Properties->Layout dialog. */ + cols = inrec.Event.WindowBufferSizeEvent.dwSize.X; + rows = inrec.Event.WindowBufferSizeEvent.dwSize.Y; + screenwidth = cols; + screenheight = rows; + w32_set_screen_dimensions (cols, rows); + display_initialize_display (screenwidth, screenheight); + window_new_screen_size (screenwidth, screenheight); + redisplay_after_signal (); + } + break; + default: + break; + } + } + } + } while (n > 0); + return nret; +} + +long +w32_chars_avail (int fd) +{ + if (w32_our_tty (fd)) + return buf_tail - buf_head; + else + { + struct stat st; + + if (fstat (fd, &st) < 0) + return 1; + else + return st.st_size; + } +} + +ssize_t +w32_read (int fd, void *buf, size_t n) +{ + if (w32_our_tty (fd)) + return w32_kbd_read (buf, n); + else + return _read (fd, buf, n); +} + +#endif /* _WIN32 */ + /* Turn on reverse video. */ static void pc_begin_inverse (void) @@ -192,6 +734,10 @@ pc_prep_terminal (void) { int tty; +#ifdef _WIN32 + w32_info_prep (); +#endif + /* Do not set screen height if we already have it, because doing so erases the screen. */ if (screenheight != ScreenRows ()) @@ -221,6 +767,10 @@ pc_unprep_terminal (void) { int tty; +#ifdef _WIN32 + w32_info_unprep (); +#endif + textattr (outside_info.normattr); /* Do not set screen height if we already have it, because @@ -230,8 +780,13 @@ pc_unprep_terminal (void) _set_screen_lines (outside_info.screenheight); textmode (LASTMODE); } +#ifdef __MSDOS__ else pc_clear_to_eol (); /* for text attributes to really take effect */ +#endif +#ifdef _WIN32 + SetConsoleScreenBufferSize (hstdout, outside_info.bufsize); +#endif /* Switch back to text mode on stdin. */ tty = fileno (stdin); @@ -256,7 +811,12 @@ pc_initialize_terminal (term_name) { term_name = getenv ("TERM"); if (!term_name) +#ifdef __MSDOS__ term_name = "pc-dos"; /* ``what's in a name?'' */ +#endif +#ifdef _WIN32 + term_name = "w32console"; +#endif } /* Get current video information, to be restored later. */ @@ -311,6 +871,7 @@ pc_initialize_terminal (term_name) pc_get_screen_size (); +#ifdef __MSDOS__ /* Store the arrow keys. */ term_ku = (char *)find_sequence (K_Up); term_kd = (char *)find_sequence (K_Down); @@ -326,6 +887,7 @@ pc_initialize_terminal (term_name) term_ki = (char *)find_sequence (K_Insert); term_kx = (char *)find_sequence (K_Delete); #endif +#endif /* __MSDOS__ */ /* Set all the hooks to our PC-specific functions. */ terminal_begin_inverse_hook = pc_begin_inverse; @@ -687,9 +1249,11 @@ kill (pid_t pid, int sig) xexit (1); case SIGUSR1: /* Simulate SIGTSTP by invoking a subsidiary shell. */ +#ifndef _WIN32 pc_goto_xy (0, outside_info.screenheight - 1); pc_clear_to_eol (); pc_write_chars (stopped_msg, sizeof (stopped_msg) - 1); +#endif /* The child shell can change the working directory, so we need to save and restore it, since it is global. */ @@ -699,7 +1263,26 @@ kill (pid_t pid, int sig) /* We don't want to get fatal signals while the subshell runs. */ old_INT = signal (SIGINT, SIG_IGN); old_QUIT = signal (SIGQUIT, SIG_IGN); +#ifdef _WIN32 + { + const char *argv[2]; + const char *shell = NULL; + + argv[0] = NULL; + shell = getenv ("SHELL"); + if (!shell) + { + shell = getenv ("COMSPEC"); + if (!shell) + return -1; + argv[0] = " /k"; + } + argv[1] = NULL; + _spawnvp (_P_WAIT, shell, argv); + } +#else system (""); +#endif if (*cwd) chdir (cwd); signal (SIGINT, old_INT); diff -ubBwp -r texinfo-4.13.orig/info/session.c texinfo-4.13/info/session.c --- texinfo-4.13.orig/info/session.c 2008-06-12 16:39:21.000000000 +0300 +++ texinfo-4.13/info/session.c 2011-08-10 09:26:30.908438400 +0300 @@ -21,7 +21,13 @@ #include "info.h" #include "search.h" +#ifndef __MINGW32__ #include <sys/ioctl.h> +#endif +#ifdef __MINGW32__ +# define read(f,b,s) w32_read(f,b,s) +# define _read(f,b,s) w32_read(f,b,s) +#endif #if defined (HAVE_SYS_TIME_H) # include <sys/time.h> @@ -5373,6 +5379,19 @@ info_gather_typeahead (void) if (chars_avail) chars_avail = read (tty, &input[0], chars_avail); } +# else +# ifdef __MINGW32__ + { + extern long w32_chars_avail (int); + + chars_avail = w32_chars_avail (tty); + + if (chars_avail > space_avail) + chars_avail = space_avail; + if (chars_avail) + chars_avail = read (tty, &input[0], chars_avail); + } +# endif /* _WIN32 */ # endif/* __DJGPP__ */ # endif /* O_NDELAY */ #endif /* !FIONREAD */ diff -ubBwp -r texinfo-4.13.orig/info/signals.c texinfo-4.13/info/signals.c --- texinfo-4.13.orig/info/signals.c 2007-07-02 01:20:31.000000000 +0300 +++ texinfo-4.13/info/signals.c 2011-11-01 15:35:24.065452900 +0200 @@ -151,7 +151,7 @@ initialize_info_signal_handler (void) #endif } -static void +void redisplay_after_signal (void) { terminal_clear_screen (); @@ -162,7 +162,7 @@ redisplay_after_signal (void) fflush (stdout); } -static void +void reset_info_window_sizes (void) { terminal_goto_xy (0, 0); diff -ubBwp -r texinfo-4.13.orig/info/termdep.h texinfo-4.13/info/termdep.h --- texinfo-4.13.orig/info/termdep.h 2007-07-02 01:20:31.000000000 +0300 +++ texinfo-4.13/info/termdep.h 2011-08-10 09:13:14.834416600 +0300 @@ -43,7 +43,9 @@ # endif /* M_XENIX */ # endif /* HAVE_SYS_PTEM_H */ # else /* !HAVE_TERMIO_H */ +# ifndef __MINGW32__ # include <sgtty.h> +# endif # endif /* !HAVE_TERMIO_H */ #endif /* !HAVE_TERMIOS_H */ @@ -55,4 +57,8 @@ # include <sys/ttold.h> #endif /* HAVE_SYS_TTOLD_H */ +#ifdef _WIN32 +extern unsigned sleep (unsigned); +#endif + #endif /* not INFO_TERMDEP_H */ diff -ubBwp -r texinfo-4.13.orig/info/terminal.c texinfo-4.13/info/terminal.c --- texinfo-4.13.orig/info/terminal.c 2008-06-12 16:39:21.000000000 +0300 +++ texinfo-4.13/info/terminal.c 2011-08-08 09:10:12.985566800 +0300 @@ -572,7 +572,9 @@ terminal_initialize_terminal (char *term ospeed = B9600; } # else +#ifndef __MINGW32__ ospeed = B9600; +#endif # endif /* !TIOCGETP */ #endif @@ -663,7 +665,9 @@ struct termio original_termio, ttybuff; /* Buffers containing the terminal mode flags upon entry to info. */ int original_tty_flags = 0; int original_lmode; +#ifndef __MINGW32__ struct sgttyb ttybuff; +#endif # if defined(TIOCGETC) && defined(M_XENIX) /* SCO 3.2v5.0.2 defines but does not support TIOCGETC. Gak. Maybe @@ -758,7 +762,7 @@ terminal_prep_terminal (void) # endif #endif -#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H) +#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H) && !defined(__MINGW32__) ioctl (tty, TIOCGETP, &ttybuff); if (!original_tty_flags) @@ -819,9 +823,11 @@ terminal_prep_terminal (void) } # endif /* TIOCGLTC */ +# ifndef __MINGW32__ ttybuff.sg_flags &= ~ECHO; ttybuff.sg_flags |= CBREAK; ioctl (tty, TIOCSETN, &ttybuff); +# endif #endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */ } @@ -846,9 +852,11 @@ terminal_unprep_terminal (void) # if defined (HAVE_TERMIO_H) ioctl (tty, TCSETA, &original_termio); # else /* !HAVE_TERMIO_H */ +# ifndef __MINGW32__ ioctl (tty, TIOCGETP, &ttybuff); ttybuff.sg_flags = original_tty_flags; ioctl (tty, TIOCSETN, &ttybuff); +# endif # if defined (TIOCGETC) ioctl (tty, TIOCSETC, &original_tchars); @@ -867,6 +875,6 @@ terminal_unprep_terminal (void) terminal_end_using_terminal (); } -#ifdef __MSDOS__ +#if defined(__MSDOS__) || defined(__MINGW32__) # include "pcterm.c" #endif diff -ubBwp -r texinfo-4.13.orig/info/tilde.c texinfo-4.13/info/tilde.c --- texinfo-4.13.orig/info/tilde.c 2008-06-12 16:39:21.000000000 +0300 +++ texinfo-4.13/info/tilde.c 2011-08-02 10:23:50.080731400 +0300 @@ -190,11 +190,15 @@ tilde_expand_word (char *filename) the password database. */ if (!temp_home) { +#ifndef __MINGW32__ struct passwd *entry; entry = (struct passwd *) getpwuid (getuid ()); if (entry) temp_home = entry->pw_dir; +#else + temp_home = "."; +#endif } temp_name = xmalloc (1 + strlen (&dirname[1]) @@ -210,7 +214,9 @@ tilde_expand_word (char *filename) } else { +#ifndef __MINGW32__ struct passwd *user_entry; +#endif char *username = xmalloc (257); int i, c; @@ -223,6 +229,7 @@ tilde_expand_word (char *filename) } username[i - 1] = 0; +#ifndef __MINGW32__ if (!(user_entry = (struct passwd *) getpwnam (username))) { /* If the calling program has a special syntax for @@ -259,6 +266,24 @@ tilde_expand_word (char *filename) endpwent (); free (username); +#else + if (tilde_expansion_failure_hook) + { + char *expansion = (*tilde_expansion_failure_hook) (username); + + if (expansion) + { + temp_name = xmalloc (1 + strlen (expansion) + + strlen (&dirname[i])); + strcpy (temp_name, expansion); + strcat (temp_name, &dirname[i]); + free (expansion); + } + } + free (dirname); + dirname = xstrdup (temp_name); + free (temp_name); +#endif } } return dirname; --- texinfo-4.13.orig/info/man.c 2011-07-25 15:15:38.299328900 +0300 +++ texinfo-4.13/info/man.c 2012-01-08 08:26:45.674020200 +0200 @@ -294,7 +294,7 @@ get_manpage_contents (char *pagename) if (manpage_section) formatter_args[arg_index++] = manpage_section; else - formatter_args[arg_index++] = "-a"; + formatter_args[arg_index++] = "-a"; formatter_args[arg_index++] = manpage_pagename; formatter_args[arg_index] = NULL; @@ -339,17 +339,23 @@ get_manpage_contents (char *pagename) /* Cannot fork/exec, but can popen/pclose. */ { FILE *fpipe; - char *cmdline = xmalloc (strlen (formatter_args[0]) - + strlen (manpage_pagename) - + (arg_index > 2 ? strlen (manpage_section) : 0) - + 3); + char *cmdline; + size_t cmdlen = 0; int save_stderr = dup (fileno (stderr)); int fd_err = open (NULL_DEVICE, O_WRONLY, 0666); + int i; + + for (i = 0; i < arg_index; i++) + cmdlen += strlen (formatter_args[i]); + /* Add-ons: 2 blanks, 2 quotes for the formatter program, 1 + terminating null character. */ + cmdlen += 2 + 2 + 1; + cmdline = xmalloc (cmdlen); if (fd_err > 2) dup2 (fd_err, fileno (stderr)); /* Don't print errors. */ - sprintf (cmdline, "%s %s %s", formatter_args[0], manpage_pagename, - arg_index > 2 ? manpage_section : ""); + sprintf (cmdline, "\"%s\" %s %s", + formatter_args[0], formatter_args[1], formatter_args[2]); fpipe = popen (cmdline, "r"); free (cmdline); if (fd_err > 2) diff -ubBwp -r texinfo-4.13.orig/makeinfo/index.c texinfo-4.13/makeinfo/index.c --- texinfo-4.13.orig/makeinfo/index.c 2008-05-22 16:11:34.000000000 +0300 +++ texinfo-4.13/makeinfo/index.c 2011-07-25 12:27:14.970722900 +0300 @@ -48,6 +48,8 @@ INDEX_ALIST **name_index_alist = NULL; command changes which array slot is pointed to by a given index. */ static INDEX_ELT **the_indices = NULL; +int mbscasecmp (const char *, const char *); + /* How to compare index entries for sorting. May be set to strcoll. */ static int (*index_compare_fn) (const char *a, const char *b) = mbscasecmp;
