| To: vim_dev@googlegroups.com |
| Subject: Patch 7.4.902 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| 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 |
| |
| |
| |
| |
| |
| *** 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); |
| |
| |
| |
| |
| *** 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 /// |