@@ -2192,8 +2192,7 @@ typedef struct ConsoleBufferStruct
21922192{
21932193 BOOL IsValid ;
21942194 CONSOLE_SCREEN_BUFFER_INFO Info ;
2195- PCHAR_INFO Buffer ;
2196- COORD BufferSize ;
2195+ HANDLE handle ;
21972196} ConsoleBuffer ;
21982197
21992198/*
@@ -2210,77 +2209,81 @@ typedef struct ConsoleBufferStruct
22102209SaveConsoleBuffer (
22112210 ConsoleBuffer * cb )
22122211{
2213- DWORD NumCells ;
2214- COORD BufferCoord ;
2215- SMALL_RECT ReadRegion ;
2216- WORD Y , Y_incr ;
2217-
22182212 if (cb == NULL )
22192213 return FALSE;
22202214
2221- if (!GetConsoleScreenBufferInfo (g_hConOut , & cb -> Info ))
2215+ if (!GetConsoleScreenBufferInfo (cb -> handle , & cb -> Info ))
22222216 {
22232217 cb -> IsValid = FALSE;
22242218 return FALSE;
22252219 }
22262220 cb -> IsValid = TRUE;
22272221
2228- /*
2229- * Allocate a buffer large enough to hold the entire console screen
2230- * buffer. If this ConsoleBuffer structure has already been initialized
2231- * with a buffer of the correct size, then just use that one.
2232- */
2233- if (!cb -> IsValid || cb -> Buffer == NULL ||
2234- cb -> BufferSize .X != cb -> Info .dwSize .X ||
2235- cb -> BufferSize .Y != cb -> Info .dwSize .Y )
2236- {
2237- cb -> BufferSize .X = cb -> Info .dwSize .X ;
2238- cb -> BufferSize .Y = cb -> Info .dwSize .Y ;
2239- NumCells = cb -> BufferSize .X * cb -> BufferSize .Y ;
2240- vim_free (cb -> Buffer );
2241- cb -> Buffer = (PCHAR_INFO )alloc (NumCells * sizeof (CHAR_INFO ));
2242- if (cb -> Buffer == NULL )
2243- return FALSE;
2244- }
2222+ return TRUE;
2223+ }
2224+
2225+ /*
2226+ * CopyOldConsoleBuffer()
2227+ * Description:
2228+ * Copies the old console buffer contents to the current console buffer.
2229+ * This is used when 'restorescreen' is off.
2230+ * Returns:
2231+ * TRUE on success
2232+ */
2233+ static BOOL
2234+ CopyOldConsoleBuffer (
2235+ ConsoleBuffer * cb ,
2236+ HANDLE hConOld )
2237+ {
2238+ COORD BufferCoord ;
2239+ COORD BufferSize ;
2240+ PCHAR_INFO Buffer ;
2241+ DWORD NumCells ;
2242+ SMALL_RECT ReadRegion ;
22452243
22462244 /*
2247- * We will now copy the console screen buffer into our buffer.
2248- * ReadConsoleOutput() seems to be limited as far as how much you
2249- * can read at a time. Empirically, this number seems to be about
2250- * 12000 cells (rows * columns). Start at position (0, 0) and copy
2251- * in chunks until it is all copied. The chunks will all have the
2252- * same horizontal characteristics, so initialize them now. The
2253- * height of each chunk will be (12000 / width).
2245+ * Before copying the buffer contents, clear the current buffer, and
2246+ * restore the window information. Doing this now prevents old buffer
2247+ * contents from "flashing" onto the screen.
22542248 */
2255- BufferCoord .X = 0 ;
2249+ ClearConsoleBuffer (cb -> Info .wAttributes );
2250+
2251+ /* We only need to copy the window area, not whole buffer. */
2252+ BufferSize .X = cb -> Info .srWindow .Right - cb -> Info .srWindow .Left + 1 ;
2253+ BufferSize .Y = cb -> Info .srWindow .Bottom - cb -> Info .srWindow .Top + 1 ;
22562254 ReadRegion .Left = 0 ;
2257- ReadRegion .Right = cb -> Info .dwSize .X - 1 ;
2258- Y_incr = 12000 / cb -> Info .dwSize .X ;
2259- for (Y = 0 ; Y < cb -> BufferSize .Y ; Y += Y_incr )
2255+ ReadRegion .Right = BufferSize .X - 1 ;
2256+ ReadRegion .Top = 0 ;
2257+ ReadRegion .Bottom = BufferSize .Y - 1 ;
2258+
2259+ NumCells = BufferSize .X * BufferSize .Y ;
2260+ Buffer = (PCHAR_INFO )alloc (NumCells * sizeof (CHAR_INFO ));
2261+ if (Buffer == NULL )
2262+ return FALSE;
2263+
2264+ BufferCoord .X = 0 ;
2265+ BufferCoord .Y = 0 ;
2266+
2267+ if (!ReadConsoleOutputW (hConOld , /* output handle */
2268+ Buffer , /* our buffer */
2269+ BufferSize , /* dimensions of our buffer */
2270+ BufferCoord , /* offset in our buffer */
2271+ & ReadRegion )) /* region to save */
22602272 {
2261- /*
2262- * Read into position (0, Y) in our buffer.
2263- */
2264- BufferCoord .Y = Y ;
2265- /*
2266- * Read the region whose top left corner is (0, Y) and whose bottom
2267- * right corner is (width - 1, Y + Y_incr - 1). This should define
2268- * a region of size width by Y_incr. Don't worry if this region is
2269- * too large for the remaining buffer; it will be cropped.
2270- */
2271- ReadRegion .Top = Y ;
2272- ReadRegion .Bottom = Y + Y_incr - 1 ;
2273- if (!ReadConsoleOutput (g_hConOut , /* output handle */
2274- cb -> Buffer , /* our buffer */
2275- cb -> BufferSize , /* dimensions of our buffer */
2276- BufferCoord , /* offset in our buffer */
2277- & ReadRegion )) /* region to save */
2278- {
2279- vim_free (cb -> Buffer );
2280- cb -> Buffer = NULL ;
2281- return FALSE;
2282- }
2273+ vim_free (Buffer );
2274+ return FALSE;
2275+ }
2276+ if (!WriteConsoleOutputW (g_hConOut , /* output handle */
2277+ Buffer , /* our buffer */
2278+ BufferSize , /* dimensions of our buffer */
2279+ BufferCoord , /* offset in our buffer */
2280+ & ReadRegion )) /* region to restore */
2281+ {
2282+ vim_free (Buffer );
2283+ return FALSE;
22832284 }
2285+ vim_free (Buffer );
2286+ SetConsoleWindowInfo (g_hConOut , TRUE, & ReadRegion );
22842287
22852288 return TRUE;
22862289}
@@ -2299,67 +2302,20 @@ RestoreConsoleBuffer(
22992302 ConsoleBuffer * cb ,
23002303 BOOL RestoreScreen )
23012304{
2302- COORD BufferCoord ;
2303- SMALL_RECT WriteRegion ;
2305+ HANDLE hConOld ;
23042306
23052307 if (cb == NULL || !cb -> IsValid )
23062308 return FALSE;
23072309
2308- /*
2309- * Before restoring the buffer contents, clear the current buffer, and
2310- * restore the cursor position and window information. Doing this now
2311- * prevents old buffer contents from "flashing" onto the screen.
2312- */
2313- if (RestoreScreen )
2314- ClearConsoleBuffer (cb -> Info .wAttributes );
2315-
2316- FitConsoleWindow (cb -> Info .dwSize , TRUE);
2317- if (!SetConsoleScreenBufferSize (g_hConOut , cb -> Info .dwSize ))
2318- return FALSE;
2319- if (!SetConsoleTextAttribute (g_hConOut , cb -> Info .wAttributes ))
2320- return FALSE;
2321-
2322- if (!RestoreScreen )
2323- {
2324- /*
2325- * No need to restore the screen buffer contents, so we're done.
2326- */
2327- return TRUE;
2328- }
2329-
2330- if (!SetConsoleCursorPosition (g_hConOut , cb -> Info .dwCursorPosition ))
2331- return FALSE;
2332- if (!SetConsoleWindowInfo (g_hConOut , TRUE, & cb -> Info .srWindow ))
2333- return FALSE;
2334-
2335- /*
2336- * Restore the screen buffer contents.
2337- */
2338- if (cb -> Buffer != NULL )
2339- {
2340- BufferCoord .X = 0 ;
2341- BufferCoord .Y = 0 ;
2342- WriteRegion .Left = 0 ;
2343- WriteRegion .Top = 0 ;
2344- WriteRegion .Right = cb -> Info .dwSize .X - 1 ;
2345- WriteRegion .Bottom = cb -> Info .dwSize .Y - 1 ;
2346- if (!WriteConsoleOutput (g_hConOut , /* output handle */
2347- cb -> Buffer , /* our buffer */
2348- cb -> BufferSize , /* dimensions of our buffer */
2349- BufferCoord , /* offset in our buffer */
2350- & WriteRegion )) /* region to restore */
2351- {
2352- return FALSE;
2353- }
2354- }
2310+ hConOld = g_hConOut ;
2311+ g_hConOut = cb -> handle ;
2312+ if (!RestoreScreen && exiting )
2313+ CopyOldConsoleBuffer (cb , hConOld );
2314+ SetConsoleActiveScreenBuffer (g_hConOut );
23552315
23562316 return TRUE;
23572317}
23582318
2359- #define FEAT_RESTORE_ORIG_SCREEN
2360- #ifdef FEAT_RESTORE_ORIG_SCREEN
2361- static ConsoleBuffer g_cbOrig = { 0 };
2362- #endif
23632319static ConsoleBuffer g_cbNonTermcap = { 0 };
23642320static ConsoleBuffer g_cbTermcap = { 0 };
23652321
@@ -2498,9 +2454,6 @@ static DWORD g_cmodeout = 0;
24982454 void
24992455mch_init (void )
25002456{
2501- #ifndef FEAT_RESTORE_ORIG_SCREEN
2502- CONSOLE_SCREEN_BUFFER_INFO csbi ;
2503- #endif
25042457#ifndef __MINGW32__
25052458 extern int _fmode ;
25062459#endif
@@ -2521,16 +2474,14 @@ mch_init(void)
25212474 else
25222475 create_conin ();
25232476 g_hConOut = GetStdHandle (STD_OUTPUT_HANDLE );
2477+ g_cbNonTermcap .handle = g_hConOut ;
2478+ g_cbTermcap .handle = CreateConsoleScreenBuffer (
2479+ GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE ,
2480+ NULL , CONSOLE_TEXTMODE_BUFFER , NULL );
25242481
2525- #ifdef FEAT_RESTORE_ORIG_SCREEN
2526- /* Save the initial console buffer for later restoration */
2527- SaveConsoleBuffer (& g_cbOrig );
2528- g_attrCurrent = g_attrDefault = g_cbOrig .Info .wAttributes ;
2529- #else
25302482 /* Get current text attributes */
2531- GetConsoleScreenBufferInfo (g_hConOut , & csbi );
2532- g_attrCurrent = g_attrDefault = csbi .wAttributes ;
2533- #endif
2483+ SaveConsoleBuffer (& g_cbNonTermcap );
2484+ g_attrCurrent = g_attrDefault = g_cbNonTermcap .Info .wAttributes ;
25342485 if (cterm_normal_fg_color == 0 )
25352486 cterm_normal_fg_color = (g_attrCurrent & 0xf ) + 1 ;
25362487 if (cterm_normal_bg_color == 0 )
@@ -2630,6 +2581,8 @@ mch_exit(int r)
26302581 SetConsoleMode (g_hConIn , g_cmodein );
26312582 SetConsoleMode (g_hConOut , g_cmodeout );
26322583
2584+ CloseHandle (g_cbTermcap .handle );
2585+
26332586#ifdef DYNAMIC_GETTEXT
26342587 dyn_libintl_end ();
26352588#endif
@@ -5002,6 +4955,8 @@ termcap_mode_start(void)
50024955 * screen buffer, and resize the buffer to match the current window
50034956 * size. We will use this as the size of our editing environment.
50044957 */
4958+ g_hConOut = g_cbTermcap .handle ;
4959+ SetConsoleActiveScreenBuffer (g_hConOut );
50054960 ClearConsoleBuffer (g_attrCurrent );
50064961 ResizeConBufAndWindow (g_hConOut , Columns , Rows );
50074962 }
@@ -5045,11 +5000,7 @@ termcap_mode_end(void)
50455000 cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT );
50465001 SetConsoleMode (g_hConIn , cmodein );
50475002
5048- #ifdef FEAT_RESTORE_ORIG_SCREEN
5049- cb = exiting ? & g_cbOrig : & g_cbNonTermcap ;
5050- #else
50515003 cb = & g_cbNonTermcap ;
5052- #endif
50535004 RestoreConsoleBuffer (cb , p_rs );
50545005 SetConsoleCursorInfo (g_hConOut , & g_cci );
50555006
0 commit comments