@@ -234,7 +234,6 @@ static int suppress_winsize = 1; /* don't fiddle with console */
234
234
235
235
static char_u * exe_path = NULL ;
236
236
237
- static BOOL is_win7 = FALSE;
238
237
static BOOL win8_or_later = FALSE;
239
238
240
239
/*
@@ -681,9 +680,6 @@ PlatformId(void)
681
680
682
681
g_PlatformId = ovi .dwPlatformId ;
683
682
684
- if ((ovi .dwMajorVersion == 6 && ovi .dwMinorVersion == 1 ))
685
- is_win7 = TRUE;
686
-
687
683
if ((ovi .dwMajorVersion == 6 && ovi .dwMinorVersion >= 2 )
688
684
|| ovi .dwMajorVersion > 6 )
689
685
win8_or_later = TRUE;
@@ -2173,7 +2169,8 @@ typedef struct ConsoleBufferStruct
2173
2169
{
2174
2170
BOOL IsValid ;
2175
2171
CONSOLE_SCREEN_BUFFER_INFO Info ;
2176
- HANDLE handle ;
2172
+ PCHAR_INFO Buffer ;
2173
+ COORD BufferSize ;
2177
2174
} ConsoleBuffer ;
2178
2175
2179
2176
/*
@@ -2190,81 +2187,77 @@ typedef struct ConsoleBufferStruct
2190
2187
SaveConsoleBuffer (
2191
2188
ConsoleBuffer * cb )
2192
2189
{
2190
+ DWORD NumCells ;
2191
+ COORD BufferCoord ;
2192
+ SMALL_RECT ReadRegion ;
2193
+ WORD Y , Y_incr ;
2194
+
2193
2195
if (cb == NULL )
2194
2196
return FALSE;
2195
2197
2196
- if (!GetConsoleScreenBufferInfo (cb -> handle , & cb -> Info ))
2198
+ if (!GetConsoleScreenBufferInfo (g_hConOut , & cb -> Info ))
2197
2199
{
2198
2200
cb -> IsValid = FALSE;
2199
2201
return FALSE;
2200
2202
}
2201
2203
cb -> IsValid = TRUE;
2202
2204
2203
- return TRUE;
2204
- }
2205
-
2206
- /*
2207
- * CopyOldConsoleBuffer()
2208
- * Description:
2209
- * Copies the old console buffer contents to the current console buffer.
2210
- * This is used when 'restorescreen' is off.
2211
- * Returns:
2212
- * TRUE on success
2213
- */
2214
- static BOOL
2215
- CopyOldConsoleBuffer (
2216
- ConsoleBuffer * cb ,
2217
- HANDLE hConOld )
2218
- {
2219
- COORD BufferCoord ;
2220
- COORD BufferSize ;
2221
- PCHAR_INFO Buffer ;
2222
- DWORD NumCells ;
2223
- SMALL_RECT ReadRegion ;
2224
-
2225
2205
/*
2226
- * Before copying the buffer contents, clear the current buffer, and
2227
- * restore the window information . Doing this now prevents old buffer
2228
- * contents from "flashing" onto the screen .
2206
+ * Allocate a buffer large enough to hold the entire console screen
2207
+ * buffer . If this ConsoleBuffer structure has already been initialized
2208
+ * with a buffer of the correct size, then just use that one .
2229
2209
*/
2230
- ClearConsoleBuffer (cb -> Info .wAttributes );
2231
-
2232
- /* We only need to copy the window area, not whole buffer. */
2233
- BufferSize .X = cb -> Info .srWindow .Right - cb -> Info .srWindow .Left + 1 ;
2234
- BufferSize .Y = cb -> Info .srWindow .Bottom - cb -> Info .srWindow .Top + 1 ;
2235
- ReadRegion .Left = 0 ;
2236
- ReadRegion .Right = BufferSize .X - 1 ;
2237
- ReadRegion .Top = 0 ;
2238
- ReadRegion .Bottom = BufferSize .Y - 1 ;
2239
-
2240
- NumCells = BufferSize .X * BufferSize .Y ;
2241
- Buffer = (PCHAR_INFO )alloc (NumCells * sizeof (CHAR_INFO ));
2242
- if (Buffer == NULL )
2243
- return FALSE;
2210
+ if (!cb -> IsValid || cb -> Buffer == NULL ||
2211
+ cb -> BufferSize .X != cb -> Info .dwSize .X ||
2212
+ cb -> BufferSize .Y != cb -> Info .dwSize .Y )
2213
+ {
2214
+ cb -> BufferSize .X = cb -> Info .dwSize .X ;
2215
+ cb -> BufferSize .Y = cb -> Info .dwSize .Y ;
2216
+ NumCells = cb -> BufferSize .X * cb -> BufferSize .Y ;
2217
+ vim_free (cb -> Buffer );
2218
+ cb -> Buffer = (PCHAR_INFO )alloc (NumCells * sizeof (CHAR_INFO ));
2219
+ if (cb -> Buffer == NULL )
2220
+ return FALSE;
2221
+ }
2244
2222
2223
+ /*
2224
+ * We will now copy the console screen buffer into our buffer.
2225
+ * ReadConsoleOutput() seems to be limited as far as how much you
2226
+ * can read at a time. Empirically, this number seems to be about
2227
+ * 12000 cells (rows * columns). Start at position (0, 0) and copy
2228
+ * in chunks until it is all copied. The chunks will all have the
2229
+ * same horizontal characteristics, so initialize them now. The
2230
+ * height of each chunk will be (12000 / width).
2231
+ */
2245
2232
BufferCoord .X = 0 ;
2246
- BufferCoord .Y = 0 ;
2247
-
2248
- if (!ReadConsoleOutputW (hConOld , /* output handle */
2249
- Buffer , /* our buffer */
2250
- BufferSize , /* dimensions of our buffer */
2251
- BufferCoord , /* offset in our buffer */
2252
- & ReadRegion )) /* region to save */
2253
- {
2254
- vim_free (Buffer );
2255
- return FALSE;
2256
- }
2257
- if (!WriteConsoleOutputW (g_hConOut , /* output handle */
2258
- Buffer , /* our buffer */
2259
- BufferSize , /* dimensions of our buffer */
2260
- BufferCoord , /* offset in our buffer */
2261
- & ReadRegion )) /* region to restore */
2233
+ ReadRegion .Left = 0 ;
2234
+ ReadRegion .Right = cb -> Info .dwSize .X - 1 ;
2235
+ Y_incr = 12000 / cb -> Info .dwSize .X ;
2236
+ for (Y = 0 ; Y < cb -> BufferSize .Y ; Y += Y_incr )
2262
2237
{
2263
- vim_free (Buffer );
2264
- return FALSE;
2238
+ /*
2239
+ * Read into position (0, Y) in our buffer.
2240
+ */
2241
+ BufferCoord .Y = Y ;
2242
+ /*
2243
+ * Read the region whose top left corner is (0, Y) and whose bottom
2244
+ * right corner is (width - 1, Y + Y_incr - 1). This should define
2245
+ * a region of size width by Y_incr. Don't worry if this region is
2246
+ * too large for the remaining buffer; it will be cropped.
2247
+ */
2248
+ ReadRegion .Top = Y ;
2249
+ ReadRegion .Bottom = Y + Y_incr - 1 ;
2250
+ if (!ReadConsoleOutput (g_hConOut , /* output handle */
2251
+ cb -> Buffer , /* our buffer */
2252
+ cb -> BufferSize , /* dimensions of our buffer */
2253
+ BufferCoord , /* offset in our buffer */
2254
+ & ReadRegion )) /* region to save */
2255
+ {
2256
+ vim_free (cb -> Buffer );
2257
+ cb -> Buffer = NULL ;
2258
+ return FALSE;
2259
+ }
2265
2260
}
2266
- vim_free (Buffer );
2267
- SetConsoleWindowInfo (g_hConOut , TRUE, & ReadRegion );
2268
2261
2269
2262
return TRUE;
2270
2263
}
@@ -2283,20 +2276,67 @@ RestoreConsoleBuffer(
2283
2276
ConsoleBuffer * cb ,
2284
2277
BOOL RestoreScreen )
2285
2278
{
2286
- HANDLE hConOld ;
2279
+ COORD BufferCoord ;
2280
+ SMALL_RECT WriteRegion ;
2287
2281
2288
2282
if (cb == NULL || !cb -> IsValid )
2289
2283
return FALSE;
2290
2284
2291
- hConOld = g_hConOut ;
2292
- g_hConOut = cb -> handle ;
2293
- if (!RestoreScreen && exiting )
2294
- CopyOldConsoleBuffer (cb , hConOld );
2295
- SetConsoleActiveScreenBuffer (g_hConOut );
2285
+ /*
2286
+ * Before restoring the buffer contents, clear the current buffer, and
2287
+ * restore the cursor position and window information. Doing this now
2288
+ * prevents old buffer contents from "flashing" onto the screen.
2289
+ */
2290
+ if (RestoreScreen )
2291
+ ClearConsoleBuffer (cb -> Info .wAttributes );
2292
+
2293
+ FitConsoleWindow (cb -> Info .dwSize , TRUE);
2294
+ if (!SetConsoleScreenBufferSize (g_hConOut , cb -> Info .dwSize ))
2295
+ return FALSE;
2296
+ if (!SetConsoleTextAttribute (g_hConOut , cb -> Info .wAttributes ))
2297
+ return FALSE;
2298
+
2299
+ if (!RestoreScreen )
2300
+ {
2301
+ /*
2302
+ * No need to restore the screen buffer contents, so we're done.
2303
+ */
2304
+ return TRUE;
2305
+ }
2306
+
2307
+ if (!SetConsoleCursorPosition (g_hConOut , cb -> Info .dwCursorPosition ))
2308
+ return FALSE;
2309
+ if (!SetConsoleWindowInfo (g_hConOut , TRUE, & cb -> Info .srWindow ))
2310
+ return FALSE;
2311
+
2312
+ /*
2313
+ * Restore the screen buffer contents.
2314
+ */
2315
+ if (cb -> Buffer != NULL )
2316
+ {
2317
+ BufferCoord .X = 0 ;
2318
+ BufferCoord .Y = 0 ;
2319
+ WriteRegion .Left = 0 ;
2320
+ WriteRegion .Top = 0 ;
2321
+ WriteRegion .Right = cb -> Info .dwSize .X - 1 ;
2322
+ WriteRegion .Bottom = cb -> Info .dwSize .Y - 1 ;
2323
+ if (!WriteConsoleOutput (g_hConOut , /* output handle */
2324
+ cb -> Buffer , /* our buffer */
2325
+ cb -> BufferSize , /* dimensions of our buffer */
2326
+ BufferCoord , /* offset in our buffer */
2327
+ & WriteRegion )) /* region to restore */
2328
+ {
2329
+ return FALSE;
2330
+ }
2331
+ }
2296
2332
2297
2333
return TRUE;
2298
2334
}
2299
2335
2336
+ #define FEAT_RESTORE_ORIG_SCREEN
2337
+ #ifdef FEAT_RESTORE_ORIG_SCREEN
2338
+ static ConsoleBuffer g_cbOrig = { 0 };
2339
+ #endif
2300
2340
static ConsoleBuffer g_cbNonTermcap = { 0 };
2301
2341
static ConsoleBuffer g_cbTermcap = { 0 };
2302
2342
@@ -2435,6 +2475,9 @@ static DWORD g_cmodeout = 0;
2435
2475
void
2436
2476
mch_init (void )
2437
2477
{
2478
+ #ifndef FEAT_RESTORE_ORIG_SCREEN
2479
+ CONSOLE_SCREEN_BUFFER_INFO csbi ;
2480
+ #endif
2438
2481
#ifndef __MINGW32__
2439
2482
extern int _fmode ;
2440
2483
#endif
@@ -2455,14 +2498,16 @@ mch_init(void)
2455
2498
else
2456
2499
create_conin ();
2457
2500
g_hConOut = GetStdHandle (STD_OUTPUT_HANDLE );
2458
- g_cbNonTermcap .handle = g_hConOut ;
2459
- g_cbTermcap .handle = CreateConsoleScreenBuffer (
2460
- GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE ,
2461
- NULL , CONSOLE_TEXTMODE_BUFFER , NULL );
2462
2501
2502
+ #ifdef FEAT_RESTORE_ORIG_SCREEN
2503
+ /* Save the initial console buffer for later restoration */
2504
+ SaveConsoleBuffer (& g_cbOrig );
2505
+ g_attrCurrent = g_attrDefault = g_cbOrig .Info .wAttributes ;
2506
+ #else
2463
2507
/* Get current text attributes */
2464
- SaveConsoleBuffer (& g_cbNonTermcap );
2465
- g_attrCurrent = g_attrDefault = g_cbNonTermcap .Info .wAttributes ;
2508
+ GetConsoleScreenBufferInfo (g_hConOut , & csbi );
2509
+ g_attrCurrent = g_attrDefault = csbi .wAttributes ;
2510
+ #endif
2466
2511
if (cterm_normal_fg_color == 0 )
2467
2512
cterm_normal_fg_color = (g_attrCurrent & 0xf ) + 1 ;
2468
2513
if (cterm_normal_bg_color == 0 )
@@ -2562,8 +2607,6 @@ mch_exit(int r)
2562
2607
SetConsoleMode (g_hConIn , g_cmodein );
2563
2608
SetConsoleMode (g_hConOut , g_cmodeout );
2564
2609
2565
- CloseHandle (g_cbTermcap .handle );
2566
-
2567
2610
#ifdef DYNAMIC_GETTEXT
2568
2611
dyn_libintl_end ();
2569
2612
#endif
@@ -4585,12 +4628,11 @@ mch_system(char *cmd, int options)
4585
4628
else
4586
4629
return mch_system_classic (cmd , options );
4587
4630
}
4588
-
4589
4631
#else
4590
4632
4591
4633
# ifdef FEAT_MBYTE
4592
4634
static int
4593
- mch_system1 (char * cmd , int options )
4635
+ mch_system (char * cmd , int options )
4594
4636
{
4595
4637
if (enc_codepage >= 0 && (int )GetACP () != enc_codepage )
4596
4638
{
@@ -4605,45 +4647,9 @@ mch_system1(char *cmd, int options)
4605
4647
return system (cmd );
4606
4648
}
4607
4649
# else
4608
- # define mch_system1 (c , o ) system(c)
4650
+ # define mch_system (c , o ) system(c)
4609
4651
# endif
4610
4652
4611
- static int
4612
- mch_system (char * cmd , int options )
4613
- {
4614
- int ret ;
4615
- HANDLE hTemp = INVALID_HANDLE_VALUE ;
4616
-
4617
- /*
4618
- * Call DuplicateHandle before executing an external program, because msys
4619
- * and msys2's programs will call CreateConsoleScreenBuffer and
4620
- * CloseHandle. CreateConsoleScreenBuffer returns the same handle which
4621
- * created by vim. This causes a crash. This workaround is required on
4622
- * Windows7.
4623
- */
4624
- if (is_win7
4625
- && g_fTermcapMode
4626
- && DuplicateHandle (
4627
- GetCurrentProcess (),
4628
- g_hConOut ,
4629
- GetCurrentProcess (),
4630
- & hTemp ,
4631
- 0 ,
4632
- TRUE,
4633
- DUPLICATE_SAME_ACCESS ))
4634
- SetConsoleActiveScreenBuffer (hTemp );
4635
-
4636
- ret = mch_system1 (cmd , options );
4637
-
4638
- if (hTemp != INVALID_HANDLE_VALUE )
4639
- {
4640
- SetConsoleActiveScreenBuffer (g_hConOut );
4641
- CloseHandle (hTemp );
4642
- }
4643
-
4644
- return ret ;
4645
- }
4646
-
4647
4653
#endif
4648
4654
4649
4655
/*
@@ -4973,8 +4979,6 @@ termcap_mode_start(void)
4973
4979
* screen buffer, and resize the buffer to match the current window
4974
4980
* size. We will use this as the size of our editing environment.
4975
4981
*/
4976
- g_hConOut = g_cbTermcap .handle ;
4977
- SetConsoleActiveScreenBuffer (g_hConOut );
4978
4982
ClearConsoleBuffer (g_attrCurrent );
4979
4983
ResizeConBufAndWindow (g_hConOut , Columns , Rows );
4980
4984
}
@@ -5018,7 +5022,11 @@ termcap_mode_end(void)
5018
5022
cmodein &= ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT );
5019
5023
SetConsoleMode (g_hConIn , cmodein );
5020
5024
5025
+ #ifdef FEAT_RESTORE_ORIG_SCREEN
5026
+ cb = exiting ? & g_cbOrig : & g_cbNonTermcap ;
5027
+ #else
5021
5028
cb = & g_cbNonTermcap ;
5029
+ #endif
5022
5030
RestoreConsoleBuffer (cb , p_rs );
5023
5031
SetConsoleCursorInfo (g_hConOut , & g_cci );
5024
5032
0 commit comments