@@ -315,6 +315,18 @@ def self.empty_buffer?
315
315
end
316
316
317
317
def self . get_console_screen_buffer_info
318
+ # CONSOLE_SCREEN_BUFFER_INFO
319
+ # [ 0,2] dwSize.X
320
+ # [ 2,2] dwSize.Y
321
+ # [ 4,2] dwCursorPositions.X
322
+ # [ 6,2] dwCursorPositions.Y
323
+ # [ 8,2] wAttributes
324
+ # [10,2] srWindow.Left
325
+ # [12,2] srWindow.Top
326
+ # [14,2] srWindow.Right
327
+ # [16,2] srWindow.Bottom
328
+ # [18,2] dwMaximumWindowSize.X
329
+ # [20,2] dwMaximumWindowSize.Y
318
330
csbi = 0 . chr * 22
319
331
return if @@GetConsoleScreenBufferInfo . call ( @@hConsoleHandle , csbi ) == 0
320
332
csbi
@@ -373,24 +385,44 @@ def self.erase_after_cursor
373
385
374
386
def self . scroll_down ( val )
375
387
return if val < 0
376
-
377
- csbi = 0 . chr * 22
378
- @@GetConsoleScreenBufferInfo . call ( @@hConsoleHandle , csbi )
379
- x , y , left , top , screen_height = csbi . unpack 'x4ssx2ssx2s'
380
-
381
- origin_x = x - left + 1
382
- origin_y = y - top + 1
383
- screen_height += 1
388
+ return unless csbi = get_console_screen_buffer_info
389
+ buffer_width , x , y , buffer_lines , attributes , window_left , window_top , window_bottom = csbi . unpack ( 'ssssSssx2s' )
390
+ screen_height = window_bottom - window_top + 1
384
391
val = screen_height if val > screen_height
385
- @@output . write [
386
- ( origin_y != screen_height ) ? "\e [#{ screen_height } ;H" : nil ,
387
- "\n " * val ,
388
- ( origin_y != screen_height or !origin_x . zero? ) ? "\e [#{ origin_y } ;#{ origin_x } H" : nil
389
- ] . join
392
+
393
+ if @@legacy_console || window_left != 0
394
+ # unless ENABLE_VIRTUAL_TERMINAL,
395
+ # if srWindow.Left != 0 then it's conhost.exe hosted console
396
+ # and puts "\n" causes horizontal scroll. its glitch.
397
+ # FYI irb write from culumn 1, so this gives no gain.
398
+ scroll_rectangle = [ 0 , val , buffer_width , buffer_lines - val ] . pack ( 's4' )
399
+ destination_origin = 0 # y * 65536 + x
400
+ fill = [ ' ' . ord , attributes ] . pack ( 'SS' )
401
+ @@ScrollConsoleScreenBuffer . call ( @@hConsoleHandle , scroll_rectangle , nil , destination_origin , fill )
402
+ else
403
+ origin_x = x + 1
404
+ origin_y = y - window_top + 1
405
+ @@output . write [
406
+ ( origin_y != screen_height ) ? "\e [#{ screen_height } ;H" : nil ,
407
+ "\n " * val ,
408
+ ( origin_y != screen_height or !x . zero? ) ? "\e [#{ origin_y } ;#{ origin_x } H" : nil
409
+ ] . join
410
+ end
390
411
end
391
412
392
413
def self . clear_screen
393
- @@output . write "\e [2J" "\e [H"
414
+ if @@legacy_console
415
+ return unless csbi = get_console_screen_buffer_info
416
+ buffer_width , buffer_lines , attributes , window_top , window_bottom = csbi . unpack ( 'ss@8S@12sx2s' )
417
+ fill_length = buffer_width * ( window_bottom - window_top + 1 )
418
+ screen_topleft = window_top * 65536
419
+ written = 0 . chr * 4
420
+ @@FillConsoleOutputCharacter . call ( @@hConsoleHandle , 0x20 , fill_length , screen_topleft , written )
421
+ @@FillConsoleOutputAttribute . call ( @@hConsoleHandle , attributes , fill_length , screen_topleft , written )
422
+ @@SetConsoleCursorPosition . call ( @@hConsoleHandle , screen_topleft )
423
+ else
424
+ @@output . write "\e [2J" "\e [H"
425
+ end
394
426
end
395
427
396
428
def self . set_screen_size ( rows , columns )
0 commit comments