Skip to content

Commit b61bc43

Browse files
committed
windows jruby issue
jruby needs terminal control with Windows API on classic console
1 parent c00930d commit b61bc43

File tree

1 file changed

+46
-14
lines changed

1 file changed

+46
-14
lines changed

lib/reline/windows.rb

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,18 @@ def self.empty_buffer?
315315
end
316316

317317
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
318330
csbi = 0.chr * 22
319331
return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
320332
csbi
@@ -373,24 +385,44 @@ def self.erase_after_cursor
373385

374386
def self.scroll_down(val)
375387
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
384391
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
390411
end
391412

392413
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
394426
end
395427

396428
def self.set_screen_size(rows, columns)

0 commit comments

Comments
 (0)