@@ -172,6 +172,14 @@ namespace stdioctl
172
172
return GetConsoleMode (h, &mode);
173
173
}
174
174
175
+ static COORD windowSize (SMALL_RECT srWindow)
176
+ {
177
+ return {
178
+ srWindow.Right - srWindow.Left + 1 ,
179
+ srWindow.Bottom - srWindow.Top + 1 ,
180
+ };
181
+ }
182
+
175
183
} // namespace stdioctl
176
184
177
185
StdioCtl::StdioCtl () noexcept
@@ -271,8 +279,7 @@ StdioCtl::StdioCtl() noexcept
271
279
// Force the screen buffer size to match the window size.
272
280
// The Console API guarantees this, but some implementations
273
281
// are not compliant (e.g. Wine).
274
- sbInfo.dwSize .X = sbInfo.srWindow .Right - sbInfo.srWindow .Left + 1 ;
275
- sbInfo.dwSize .Y = sbInfo.srWindow .Bottom - sbInfo.srWindow .Top + 1 ;
282
+ sbInfo.dwSize = windowSize (sbInfo.srWindow );
276
283
SetConsoleScreenBufferSize (cn[activeOutput].handle , sbInfo.dwSize );
277
284
}
278
285
SetConsoleActiveScreenBuffer (cn[activeOutput].handle );
@@ -286,6 +293,40 @@ StdioCtl::StdioCtl() noexcept
286
293
287
294
StdioCtl::~StdioCtl ()
288
295
{
296
+ using namespace stdioctl ;
297
+ CONSOLE_SCREEN_BUFFER_INFO activeSbInfo {};
298
+ GetConsoleScreenBufferInfo (cn[activeOutput].handle , &activeSbInfo);
299
+ CONSOLE_SCREEN_BUFFER_INFO startupSbInfo {};
300
+ GetConsoleScreenBufferInfo (cn[startupOutput].handle , &startupSbInfo);
301
+
302
+ COORD activeWindowSize = windowSize (activeSbInfo.srWindow );
303
+ COORD startupWindowSize = windowSize (startupSbInfo.srWindow );
304
+
305
+ // Preserve the current window size.
306
+ if ( activeWindowSize.X != startupWindowSize.X ||
307
+ activeWindowSize.Y != startupWindowSize.Y )
308
+ {
309
+ // The buffer is not allowed to be smaller than the window, so enlarge
310
+ // it if necessary. But do not shrink it in the opposite case, to avoid
311
+ // loss of data.
312
+ COORD dwSize = startupSbInfo.dwSize ;
313
+ if (dwSize.X < activeWindowSize.X )
314
+ dwSize.X = activeWindowSize.X ;
315
+ if (dwSize.Y < activeWindowSize.Y )
316
+ dwSize.Y = activeWindowSize.Y ;
317
+ SetConsoleScreenBufferSize (cn[startupOutput].handle , dwSize);
318
+ // Get the updated cursor position, in case it changed after the resize.
319
+ GetConsoleScreenBufferInfo (cn[startupOutput].handle , &startupSbInfo);
320
+ // Make sure the cursor is visible. If possible, show it in the bottom row.
321
+ SMALL_RECT srWindow = startupSbInfo.srWindow ;
322
+ COORD dwCursorPosition = startupSbInfo.dwCursorPosition ;
323
+ srWindow.Right = max (dwCursorPosition.X , activeWindowSize.X - 1 );
324
+ srWindow.Left = srWindow.Right - (activeWindowSize.X - 1 );
325
+ srWindow.Bottom = max (dwCursorPosition.Y , activeWindowSize.Y - 1 );
326
+ srWindow.Top = srWindow.Bottom - (activeWindowSize.Y - 1 );
327
+ SetConsoleWindowInfo (cn[startupOutput].handle , TRUE , &srWindow);
328
+ }
329
+
289
330
SetConsoleActiveScreenBuffer (cn[startupOutput].handle );
290
331
for (auto &c : cn)
291
332
if (c.owning )
0 commit comments