From 2a8ff602e0a6302faef92d554fc809aef3b71212 Mon Sep 17 00:00:00 2001 From: YO4 Date: Fri, 17 Dec 2021 18:22:59 +0900 Subject: [ruby/reline] windows jruby issue jruby needs terminal control with Windows API on classic console https://github.com/ruby/reline/commit/b61bc43374 --- lib/reline/windows.rb | 60 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb index 8710e6cb80..e7b8957115 100644 --- a/lib/reline/windows.rb +++ b/lib/reline/windows.rb @@ -315,6 +315,18 @@ class Reline::Windows end def self.get_console_screen_buffer_info + # CONSOLE_SCREEN_BUFFER_INFO + # [ 0,2] dwSize.X + # [ 2,2] dwSize.Y + # [ 4,2] dwCursorPositions.X + # [ 6,2] dwCursorPositions.Y + # [ 8,2] wAttributes + # [10,2] srWindow.Left + # [12,2] srWindow.Top + # [14,2] srWindow.Right + # [16,2] srWindow.Bottom + # [18,2] dwMaximumWindowSize.X + # [20,2] dwMaximumWindowSize.Y csbi = 0.chr * 22 return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0 csbi @@ -373,24 +385,44 @@ class Reline::Windows def self.scroll_down(val) return if val < 0 - - csbi = 0.chr * 22 - @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) - x, y, left, top, screen_height = csbi.unpack 'x4ssx2ssx2s' - - origin_x = x - left + 1 - origin_y = y - top + 1 - screen_height += 1 + return unless csbi = get_console_screen_buffer_info + buffer_width, x, y, buffer_lines, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s') + screen_height = window_bottom - window_top + 1 val = screen_height if val > screen_height - @@output.write [ - (origin_y != screen_height) ? "\e[#{screen_height};H" : nil, - "\n" * val, - (origin_y != screen_height or !origin_x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil - ].join + + if @@legacy_console || window_left != 0 + # unless ENABLE_VIRTUAL_TERMINAL, + # if srWindow.Left != 0 then it's conhost.exe hosted console + # and puts "\n" causes horizontal scroll. its glitch. + # FYI irb write from culumn 1, so this gives no gain. + scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4') + destination_origin = 0 # y * 65536 + x + fill = [' '.ord, attributes].pack('SS') + @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill) + else + origin_x = x + 1 + origin_y = y - window_top + 1 + @@output.write [ + (origin_y != screen_height) ? "\e[#{screen_height};H" : nil, + "\n" * val, + (origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil + ].join + end end def self.clear_screen - @@output.write "\e[2J" "\e[H" + if @@legacy_console + return unless csbi = get_console_screen_buffer_info + buffer_width, buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s') + fill_length = buffer_width * (window_bottom - window_top + 1) + screen_topleft = window_top * 65536 + written = 0.chr * 4 + @@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, fill_length, screen_topleft, written) + @@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, fill_length, screen_topleft, written) + @@SetConsoleCursorPosition.call(@@hConsoleHandle, screen_topleft) + else + @@output.write "\e[2J" "\e[H" + end end def self.set_screen_size(rows, columns) -- cgit v1.2.3