To: vim_dev@googlegroups.com Subject: Patch 7.4.902 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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) Files: src/os_win32.c *** ../vim-7.4.901/src/os_win32.c 2015-09-29 14:01:08.059935930 +0200 --- src/os_win32.c 2015-10-30 16:43:34.543013902 +0100 *************** *** 234,240 **** static char_u *exe_path = NULL; - static BOOL is_win7 = FALSE; static BOOL win8_or_later = FALSE; /* --- 234,239 ---- *************** *** 681,689 **** g_PlatformId = ovi.dwPlatformId; - if ((ovi.dwMajorVersion == 6 && ovi.dwMinorVersion == 1)) - is_win7 = TRUE; - if ((ovi.dwMajorVersion == 6 && ovi.dwMinorVersion >= 2) || ovi.dwMajorVersion > 6) win8_or_later = TRUE; --- 680,685 ---- *************** *** 2173,2179 **** { BOOL IsValid; CONSOLE_SCREEN_BUFFER_INFO Info; ! HANDLE handle; } ConsoleBuffer; /* --- 2169,2176 ---- { BOOL IsValid; CONSOLE_SCREEN_BUFFER_INFO Info; ! PCHAR_INFO Buffer; ! COORD BufferSize; } ConsoleBuffer; /* *************** *** 2190,2270 **** SaveConsoleBuffer( ConsoleBuffer *cb) { if (cb == NULL) return FALSE; ! if (!GetConsoleScreenBufferInfo(cb->handle, &cb->Info)) { cb->IsValid = FALSE; return FALSE; } cb->IsValid = TRUE; - return TRUE; - } - - /* - * CopyOldConsoleBuffer() - * Description: - * Copies the old console buffer contents to the current console buffer. - * This is used when 'restorescreen' is off. - * Returns: - * TRUE on success - */ - static BOOL - CopyOldConsoleBuffer( - ConsoleBuffer *cb, - HANDLE hConOld) - { - COORD BufferCoord; - COORD BufferSize; - PCHAR_INFO Buffer; - DWORD NumCells; - SMALL_RECT ReadRegion; - /* ! * Before copying the buffer contents, clear the current buffer, and ! * restore the window information. Doing this now prevents old buffer ! * contents from "flashing" onto the screen. */ ! 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.Y = 0; ! ! if (!ReadConsoleOutputW(hConOld, /* output handle */ ! Buffer, /* our buffer */ ! BufferSize, /* dimensions of our buffer */ ! BufferCoord, /* offset in our buffer */ ! &ReadRegion)) /* region to save */ ! { ! vim_free(Buffer); ! 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; } --- 2187,2263 ---- SaveConsoleBuffer( ConsoleBuffer *cb) { + DWORD NumCells; + COORD BufferCoord; + SMALL_RECT ReadRegion; + WORD Y, Y_incr; + if (cb == NULL) return FALSE; ! if (!GetConsoleScreenBufferInfo(g_hConOut, &cb->Info)) { cb->IsValid = FALSE; return FALSE; } cb->IsValid = 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. */ ! if (!cb->IsValid || cb->Buffer == NULL || ! cb->BufferSize.X != cb->Info.dwSize.X || ! cb->BufferSize.Y != cb->Info.dwSize.Y) ! { ! cb->BufferSize.X = cb->Info.dwSize.X; ! cb->BufferSize.Y = cb->Info.dwSize.Y; ! NumCells = cb->BufferSize.X * cb->BufferSize.Y; ! vim_free(cb->Buffer); ! cb->Buffer = (PCHAR_INFO)alloc(NumCells * sizeof(CHAR_INFO)); ! if (cb->Buffer == NULL) ! return FALSE; ! } + /* + * We will now copy the console screen buffer into our buffer. + * ReadConsoleOutput() seems to be limited as far as how much you + * 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). + */ BufferCoord.X = 0; ! ReadRegion.Left = 0; ! ReadRegion.Right = cb->Info.dwSize.X - 1; ! Y_incr = 12000 / cb->Info.dwSize.X; ! for (Y = 0; Y < cb->BufferSize.Y; Y += Y_incr) { ! /* ! * 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; ! } } return TRUE; } *************** *** 2283,2302 **** ConsoleBuffer *cb, BOOL RestoreScreen) { ! HANDLE hConOld; if (cb == NULL || !cb->IsValid) return FALSE; ! hConOld = g_hConOut; ! g_hConOut = cb->handle; ! if (!RestoreScreen && exiting) ! CopyOldConsoleBuffer(cb, hConOld); ! SetConsoleActiveScreenBuffer(g_hConOut); return TRUE; } static ConsoleBuffer g_cbNonTermcap = { 0 }; static ConsoleBuffer g_cbTermcap = { 0 }; --- 2276,2342 ---- ConsoleBuffer *cb, BOOL RestoreScreen) { ! COORD BufferCoord; ! SMALL_RECT WriteRegion; if (cb == NULL || !cb->IsValid) return FALSE; ! /* ! * Before restoring the buffer contents, clear the current buffer, and ! * restore the cursor position and window information. Doing this now ! * prevents old buffer contents from "flashing" onto the screen. ! */ ! 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; } + #define FEAT_RESTORE_ORIG_SCREEN + #ifdef FEAT_RESTORE_ORIG_SCREEN + static ConsoleBuffer g_cbOrig = { 0 }; + #endif static ConsoleBuffer g_cbNonTermcap = { 0 }; static ConsoleBuffer g_cbTermcap = { 0 }; *************** *** 2435,2440 **** --- 2475,2483 ---- void mch_init(void) { + #ifndef FEAT_RESTORE_ORIG_SCREEN + CONSOLE_SCREEN_BUFFER_INFO csbi; + #endif #ifndef __MINGW32__ extern int _fmode; #endif *************** *** 2455,2468 **** else create_conin(); 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); /* Get current text attributes */ ! SaveConsoleBuffer(&g_cbNonTermcap); ! g_attrCurrent = g_attrDefault = g_cbNonTermcap.Info.wAttributes; if (cterm_normal_fg_color == 0) cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1; if (cterm_normal_bg_color == 0) --- 2498,2513 ---- else create_conin(); g_hConOut = GetStdHandle(STD_OUTPUT_HANDLE); + #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 */ ! GetConsoleScreenBufferInfo(g_hConOut, &csbi); ! g_attrCurrent = g_attrDefault = csbi.wAttributes; ! #endif if (cterm_normal_fg_color == 0) cterm_normal_fg_color = (g_attrCurrent & 0xf) + 1; if (cterm_normal_bg_color == 0) *************** *** 2562,2569 **** SetConsoleMode(g_hConIn, g_cmodein); SetConsoleMode(g_hConOut, g_cmodeout); - CloseHandle(g_cbTermcap.handle); - #ifdef DYNAMIC_GETTEXT dyn_libintl_end(); #endif --- 2607,2612 ---- *************** *** 4585,4596 **** else return mch_system_classic(cmd, options); } - #else # ifdef FEAT_MBYTE static int ! mch_system1(char *cmd, int options) { if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { --- 4628,4638 ---- else return mch_system_classic(cmd, options); } #else # ifdef FEAT_MBYTE static int ! mch_system(char *cmd, int options) { if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { *************** *** 4605,4649 **** return system(cmd); } # else ! # define mch_system1(c, o) system(c) # 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 /* --- 4647,4655 ---- return system(cmd); } # else ! # define mch_system(c, o) system(c) # endif #endif /* *************** *** 4973,4980 **** * screen buffer, and resize the buffer to match the current window * size. We will use this as the size of our editing environment. */ - g_hConOut = g_cbTermcap.handle; - SetConsoleActiveScreenBuffer(g_hConOut); ClearConsoleBuffer(g_attrCurrent); ResizeConBufAndWindow(g_hConOut, Columns, Rows); } --- 4979,4984 ---- *************** *** 5018,5024 **** --- 5022,5032 ---- cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); SetConsoleMode(g_hConIn, cmodein); + #ifdef FEAT_RESTORE_ORIG_SCREEN + cb = exiting ? &g_cbOrig : &g_cbNonTermcap; + #else cb = &g_cbNonTermcap; + #endif RestoreConsoleBuffer(cb, p_rs); SetConsoleCursorInfo(g_hConOut, &g_cci); *** ../vim-7.4.901/src/version.c 2015-10-30 14:23:29.158200567 +0100 --- src/version.c 2015-10-30 16:45:09.697887553 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 902, /**/ -- Q: Should I clean my house or work on Vim? A: Whatever contains more bugs. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///