patch 7.4.902

Problem:    Problems with using the MS-Windows console.
Solution:   Revert patches 7.4.851, 7.4.876 and 7.4.886 until we find a better
            solution. (suggested by Ken Takata)
This commit is contained in:
Bram Moolenaar
2015-10-30 16:46:55 +01:00
parent a0f849ee40
commit 4c0aac5759
2 changed files with 130 additions and 120 deletions

View File

@ -234,7 +234,6 @@ static int suppress_winsize = 1; /* don't fiddle with console */
static char_u *exe_path = NULL; static char_u *exe_path = NULL;
static BOOL is_win7 = FALSE;
static BOOL win8_or_later = FALSE; static BOOL win8_or_later = FALSE;
/* /*
@ -681,9 +680,6 @@ PlatformId(void)
g_PlatformId = ovi.dwPlatformId; g_PlatformId = ovi.dwPlatformId;
if ((ovi.dwMajorVersion == 6 && ovi.dwMinorVersion == 1))
is_win7 = TRUE;
if ((ovi.dwMajorVersion == 6 && ovi.dwMinorVersion >= 2) if ((ovi.dwMajorVersion == 6 && ovi.dwMinorVersion >= 2)
|| ovi.dwMajorVersion > 6) || ovi.dwMajorVersion > 6)
win8_or_later = TRUE; win8_or_later = TRUE;
@ -2173,7 +2169,8 @@ typedef struct ConsoleBufferStruct
{ {
BOOL IsValid; BOOL IsValid;
CONSOLE_SCREEN_BUFFER_INFO Info; CONSOLE_SCREEN_BUFFER_INFO Info;
HANDLE handle; PCHAR_INFO Buffer;
COORD BufferSize;
} ConsoleBuffer; } ConsoleBuffer;
/* /*
@ -2190,81 +2187,77 @@ typedef struct ConsoleBufferStruct
SaveConsoleBuffer( SaveConsoleBuffer(
ConsoleBuffer *cb) ConsoleBuffer *cb)
{ {
DWORD NumCells;
COORD BufferCoord;
SMALL_RECT ReadRegion;
WORD Y, Y_incr;
if (cb == NULL) if (cb == NULL)
return FALSE; return FALSE;
if (!GetConsoleScreenBufferInfo(cb->handle, &cb->Info)) if (!GetConsoleScreenBufferInfo(g_hConOut, &cb->Info))
{ {
cb->IsValid = FALSE; cb->IsValid = FALSE;
return FALSE; return FALSE;
} }
cb->IsValid = TRUE; cb->IsValid = TRUE;
return TRUE; /*
} * Allocate a buffer large enough to hold the entire console screen
* buffer. If this ConsoleBuffer structure has already been initialized
/* * with a buffer of the correct size, then just use that one.
* CopyOldConsoleBuffer() */
* Description: if (!cb->IsValid || cb->Buffer == NULL ||
* Copies the old console buffer contents to the current console buffer. cb->BufferSize.X != cb->Info.dwSize.X ||
* This is used when 'restorescreen' is off. cb->BufferSize.Y != cb->Info.dwSize.Y)
* Returns: {
* TRUE on success cb->BufferSize.X = cb->Info.dwSize.X;
*/ cb->BufferSize.Y = cb->Info.dwSize.Y;
static BOOL NumCells = cb->BufferSize.X * cb->BufferSize.Y;
CopyOldConsoleBuffer( vim_free(cb->Buffer);
ConsoleBuffer *cb, cb->Buffer = (PCHAR_INFO)alloc(NumCells * sizeof(CHAR_INFO));
HANDLE hConOld) if (cb->Buffer == NULL)
{ return FALSE;
COORD BufferCoord; }
COORD BufferSize;
PCHAR_INFO Buffer;
DWORD NumCells;
SMALL_RECT ReadRegion;
/* /*
* Before copying the buffer contents, clear the current buffer, and * We will now copy the console screen buffer into our buffer.
* restore the window information. Doing this now prevents old buffer * ReadConsoleOutput() seems to be limited as far as how much you
* contents from "flashing" onto the screen. * can read at a time. Empirically, this number seems to be about
* 12000 cells (rows * columns). Start at position (0, 0) and copy
* in chunks until it is all copied. The chunks will all have the
* same horizontal characteristics, so initialize them now. The
* height of each chunk will be (12000 / width).
*/ */
ClearConsoleBuffer(cb->Info.wAttributes);
/* We only need to copy the window area, not whole buffer. */
BufferSize.X = cb->Info.srWindow.Right - cb->Info.srWindow.Left + 1;
BufferSize.Y = cb->Info.srWindow.Bottom - cb->Info.srWindow.Top + 1;
ReadRegion.Left = 0;
ReadRegion.Right = BufferSize.X - 1;
ReadRegion.Top = 0;
ReadRegion.Bottom = BufferSize.Y - 1;
NumCells = BufferSize.X * BufferSize.Y;
Buffer = (PCHAR_INFO)alloc(NumCells * sizeof(CHAR_INFO));
if (Buffer == NULL)
return FALSE;
BufferCoord.X = 0; BufferCoord.X = 0;
BufferCoord.Y = 0; ReadRegion.Left = 0;
ReadRegion.Right = cb->Info.dwSize.X - 1;
if (!ReadConsoleOutputW(hConOld, /* output handle */ Y_incr = 12000 / cb->Info.dwSize.X;
Buffer, /* our buffer */ for (Y = 0; Y < cb->BufferSize.Y; Y += Y_incr)
BufferSize, /* dimensions of our buffer */
BufferCoord, /* offset in our buffer */
&ReadRegion)) /* region to save */
{ {
vim_free(Buffer); /*
return FALSE; * Read into position (0, Y) in our buffer.
*/
BufferCoord.Y = Y;
/*
* Read the region whose top left corner is (0, Y) and whose bottom
* right corner is (width - 1, Y + Y_incr - 1). This should define
* a region of size width by Y_incr. Don't worry if this region is
* too large for the remaining buffer; it will be cropped.
*/
ReadRegion.Top = Y;
ReadRegion.Bottom = Y + Y_incr - 1;
if (!ReadConsoleOutput(g_hConOut, /* output handle */
cb->Buffer, /* our buffer */
cb->BufferSize, /* dimensions of our buffer */
BufferCoord, /* offset in our buffer */
&ReadRegion)) /* region to save */
{
vim_free(cb->Buffer);
cb->Buffer = NULL;
return FALSE;
}
} }
if (!WriteConsoleOutputW(g_hConOut, /* output handle */
Buffer, /* our buffer */
BufferSize, /* dimensions of our buffer */
BufferCoord, /* offset in our buffer */
&ReadRegion)) /* region to restore */
{
vim_free(Buffer);
return FALSE;
}
vim_free(Buffer);
SetConsoleWindowInfo(g_hConOut, TRUE, &ReadRegion);
return TRUE; return TRUE;
} }
@ -2283,20 +2276,67 @@ RestoreConsoleBuffer(
ConsoleBuffer *cb, ConsoleBuffer *cb,
BOOL RestoreScreen) BOOL RestoreScreen)
{ {
HANDLE hConOld; COORD BufferCoord;
SMALL_RECT WriteRegion;
if (cb == NULL || !cb->IsValid) if (cb == NULL || !cb->IsValid)
return FALSE; return FALSE;
hConOld = g_hConOut; /*
g_hConOut = cb->handle; * Before restoring the buffer contents, clear the current buffer, and
if (!RestoreScreen && exiting) * restore the cursor position and window information. Doing this now
CopyOldConsoleBuffer(cb, hConOld); * prevents old buffer contents from "flashing" onto the screen.
SetConsoleActiveScreenBuffer(g_hConOut); */
if (RestoreScreen)
ClearConsoleBuffer(cb->Info.wAttributes);
FitConsoleWindow(cb->Info.dwSize, TRUE);
if (!SetConsoleScreenBufferSize(g_hConOut, cb->Info.dwSize))
return FALSE;
if (!SetConsoleTextAttribute(g_hConOut, cb->Info.wAttributes))
return FALSE;
if (!RestoreScreen)
{
/*
* No need to restore the screen buffer contents, so we're done.
*/
return TRUE;
}
if (!SetConsoleCursorPosition(g_hConOut, cb->Info.dwCursorPosition))
return FALSE;
if (!SetConsoleWindowInfo(g_hConOut, TRUE, &cb->Info.srWindow))
return FALSE;
/*
* Restore the screen buffer contents.
*/
if (cb->Buffer != NULL)
{
BufferCoord.X = 0;
BufferCoord.Y = 0;
WriteRegion.Left = 0;
WriteRegion.Top = 0;
WriteRegion.Right = cb->Info.dwSize.X - 1;
WriteRegion.Bottom = cb->Info.dwSize.Y - 1;
if (!WriteConsoleOutput(g_hConOut, /* output handle */
cb->Buffer, /* our buffer */
cb->BufferSize, /* dimensions of our buffer */
BufferCoord, /* offset in our buffer */
&WriteRegion)) /* region to restore */
{
return FALSE;
}
}
return TRUE; return TRUE;
} }
#define FEAT_RESTORE_ORIG_SCREEN
#ifdef FEAT_RESTORE_ORIG_SCREEN
static ConsoleBuffer g_cbOrig = { 0 };
#endif
static ConsoleBuffer g_cbNonTermcap = { 0 }; static ConsoleBuffer g_cbNonTermcap = { 0 };
static ConsoleBuffer g_cbTermcap = { 0 }; static ConsoleBuffer g_cbTermcap = { 0 };
@ -2435,6 +2475,9 @@ static DWORD g_cmodeout = 0;
void void
mch_init(void) mch_init(void)
{ {
#ifndef FEAT_RESTORE_ORIG_SCREEN
CONSOLE_SCREEN_BUFFER_INFO csbi;
#endif
#ifndef __MINGW32__ #ifndef __MINGW32__
extern int _fmode; extern int _fmode;
#endif #endif
@ -2455,14 +2498,16 @@ mch_init(void)
else else
create_conin(); create_conin();
g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE); g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
g_cbNonTermcap.handle = g_hConOut;
g_cbTermcap.handle = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
#ifdef FEAT_RESTORE_ORIG_SCREEN
/* Save the initial console buffer for later restoration */
SaveConsoleBuffer(&g_cbOrig);
g_attrCurrent = g_attrDefault = g_cbOrig.Info.wAttributes;
#else
/* Get current text attributes */ /* Get current text attributes */
SaveConsoleBuffer(&g_cbNonTermcap); GetConsoleScreenBufferInfo(g_hConOut, &csbi);
g_attrCurrent = g_attrDefault = g_cbNonTermcap.Info.wAttributes; g_attrCurrent = g_attrDefault = csbi.wAttributes;
#endif
if (cterm_normal_fg_color == 0) if (cterm_normal_fg_color == 0)
cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1; cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1;
if (cterm_normal_bg_color == 0) if (cterm_normal_bg_color == 0)
@ -2562,8 +2607,6 @@ mch_exit(int r)
SetConsoleMode(g_hConIn, g_cmodein); SetConsoleMode(g_hConIn, g_cmodein);
SetConsoleMode(g_hConOut, g_cmodeout); SetConsoleMode(g_hConOut, g_cmodeout);
CloseHandle(g_cbTermcap.handle);
#ifdef DYNAMIC_GETTEXT #ifdef DYNAMIC_GETTEXT
dyn_libintl_end(); dyn_libintl_end();
#endif #endif
@ -4585,12 +4628,11 @@ mch_system(char *cmd, int options)
else else
return mch_system_classic(cmd, options); return mch_system_classic(cmd, options);
} }
#else #else
# ifdef FEAT_MBYTE # ifdef FEAT_MBYTE
static int static int
mch_system1(char *cmd, int options) mch_system(char *cmd, int options)
{ {
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
{ {
@ -4605,45 +4647,9 @@ mch_system1(char *cmd, int options)
return system(cmd); return system(cmd);
} }
# else # else
# define mch_system1(c, o) system(c) # define mch_system(c, o) system(c)
# endif # endif
static int
mch_system(char *cmd, int options)
{
int ret;
HANDLE hTemp = INVALID_HANDLE_VALUE;
/*
* Call DuplicateHandle before executing an external program, because msys
* and msys2's programs will call CreateConsoleScreenBuffer and
* CloseHandle. CreateConsoleScreenBuffer returns the same handle which
* created by vim. This causes a crash. This workaround is required on
* Windows7.
*/
if (is_win7
&& g_fTermcapMode
&& DuplicateHandle(
GetCurrentProcess(),
g_hConOut,
GetCurrentProcess(),
&hTemp,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
SetConsoleActiveScreenBuffer(hTemp);
ret = mch_system1(cmd, options);
if (hTemp != INVALID_HANDLE_VALUE)
{
SetConsoleActiveScreenBuffer(g_hConOut);
CloseHandle(hTemp);
}
return ret;
}
#endif #endif
/* /*
@ -4973,8 +4979,6 @@ termcap_mode_start(void)
* screen buffer, and resize the buffer to match the current window * screen buffer, and resize the buffer to match the current window
* size. We will use this as the size of our editing environment. * size. We will use this as the size of our editing environment.
*/ */
g_hConOut = g_cbTermcap.handle;
SetConsoleActiveScreenBuffer(g_hConOut);
ClearConsoleBuffer(g_attrCurrent); ClearConsoleBuffer(g_attrCurrent);
ResizeConBufAndWindow(g_hConOut, Columns, Rows); ResizeConBufAndWindow(g_hConOut, Columns, Rows);
} }
@ -5018,7 +5022,11 @@ termcap_mode_end(void)
cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
SetConsoleMode(g_hConIn, cmodein); SetConsoleMode(g_hConIn, cmodein);
#ifdef FEAT_RESTORE_ORIG_SCREEN
cb = exiting ? &g_cbOrig : &g_cbNonTermcap;
#else
cb = &g_cbNonTermcap; cb = &g_cbNonTermcap;
#endif
RestoreConsoleBuffer(cb, p_rs); RestoreConsoleBuffer(cb, p_rs);
SetConsoleCursorInfo(g_hConOut, &g_cci); SetConsoleCursorInfo(g_hConOut, &g_cci);

View File

@ -741,6 +741,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
902,
/**/ /**/
901, 901,
/**/ /**/