|
|
What this is
This file is included in the DevDaily.com
"Ruby Source Code
Warehouse" project. The intent of this project is to help you "Learn
Ruby by Example" TM.
Other links
The source code
# Win32::Console: an object implementing the Win32 API Console functions
# Copyright (C) 2003 Gonzalo Garramuno (ggarramuno@aol.com)
#
# Original Win32API_Console was:
# Copyright (C) 2001 Michael L. Semon (mlsemon@sega.net)
begin
# If Console.so is available, use that. Otherwise, we define
# equivalent functions in ruby (a tad slower)
# That dll should define everything in an identical interface
# to all the ruby code that the rescue below defines.
require "Console.so"
STDERR.print "Using faster, DLL Console.so\n" if $DEBUG
rescue Exception
STDERR.print "Using slower, non-DLL Console.rb\n" if $DEBUG
module Win32
class Console
end
end
# The WINDOWS constants
module Win32::Console::Constants
STD_INPUT_HANDLE = 0xFFFFFFF6
STD_OUTPUT_HANDLE = 0xFFFFFFF5
STD_ERROR_HANDLE = 0xFFFFFFF4
INVALID_HANDLE_VALUE = 0xFFFFFFFF
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
CONSOLE_TEXTMODE_BUFFER = 0x00000001
FOREGROUND_BLUE = 0x0001
FOREGROUND_GREEN = 0x0002
FOREGROUND_RED = 0x0004
FOREGROUND_INTENSITY = 0x0008
BACKGROUND_BLUE = 0x0010
BACKGROUND_GREEN = 0x0020
BACKGROUND_RED = 0x0040
BACKGROUND_INTENSITY = 0x0080
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
KEY_EVENT = 0x0001
MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004
MENU_EVENT = 0x0008
FOCUS_EVENT = 0x0010
CAPSLOCK_ON = 0x0080
ENHANCED_KEY = 0x0100
NUMLOCK_ON = 0x0020
SHIFT_PRESSED = 0x0010
LEFT_CTRL_PRESSED = 0x0008
RIGHT_CTRL_PRESSED = 0x0004
LEFT_ALT_PRESSED = 0x0002
RIGHT_ALT_PRESSED = 0x0001
SCROLLLOCK_ON = 0x0040
MOUSE_WHEELED = 0x0004
DOUBLE_CLICK = 0x0002
MOUSE_MOVED = 0x0001
FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001
FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004
FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008
FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010
RIGHTMOST_BUTTON_PRESSED = 0x0002
CTRL_C_EVENT = 0x0000
CTRL_BREAK_EVENT = 0x0001
CTRL_CLOSE_EVENT = 0x0002
CTRL_LOGOFF_EVENT = 0x0005
CTRL_SHUTDOWN_EVENT = 0x0006
end
# The actual api to access windows functions
class Win32::Console::API
require 'Win32API'
private
# This is a class-wide cache that will hold Win32API objects. As each
# Win32API object is about 920 bytes, I didn't want to initialize all of
# them at one time. That would waste about 42 kB for this object because
# it has 47 functions. However, to not have a cache at all would reduce
# the speed of this object by 164%.
@@m_AllocConsole = nil
@@m_CreateConsoleScreenBuffer = nil
@@m_FillConsoleOutputAttribute = nil
@@m_FillConsoleOutputCharacter = nil
@@m_FlushConsoleInputBuffer = nil
@@m_FreeConsole = nil
@@m_GenerateConsoleCtrlEvent = nil
@@m_GetConsoleCP = nil
@@m_GetConsoleCursorInfo = nil
@@m_GetConsoleMode = nil
@@m_GetConsoleOutputCP = nil
@@m_GetConsoleScreenBufferInfo = nil
@@m_GetConsoleTitle = nil
@@m_GetConsoleWindow = nil
@@m_GetLargestConsoleWindowSize = nil
@@m_GetNumberOfConsoleInputEvents = nil
@@m_GetNumberOfConsoleMouseButtons = nil
@@m_GetStdHandle = nil
@@m_PeekConsoleInput = nil
@@m_ReadConsole = nil
@@m_ReadConsoleInput = nil
@@m_ReadConsoleOutput = nil
@@m_ReadConsoleOutputAttribute = nil
@@m_ReadConsoleOutputCharacter = nil
@@m_ScrollConsoleScreenBuffer = nil
@@m_SetConsoleActiveScreenBuffer = nil
@@m_SetConsoleCP = nil
@@m_SetConsoleCursorInfo = nil
@@m_SetConsoleCursorPosition = nil
@@m_SetConsoleMode = nil
@@m_SetConsoleOutputCP = nil
@@m_SetConsoleScreenBufferSize = nil
@@m_SetConsoleTextAttribute = nil
@@m_SetConsoleTitle = nil
@@m_SetConsoleWindowInfo = nil
@@m_SetStdHandle = nil
@@m_WriteConsole = nil
@@m_WriteConsoleInput = nil
@@m_WriteConsoleOutput = nil
@@m_WriteConsoleOutputAttribute = nil
@@m_WriteConsoleOutputCharacter = nil
public
class << self
def constant(t)
begin
eval "return Win32::Console::Constants::#{t}"
rescue
return nil
end
end
def AllocConsole()
if @@m_AllocConsole == nil
@@m_AllocConsole = Win32API.new( "kernel32", "AllocConsole",
[], 'l' )
end
@@m_AllocConsole.call()
end
def CreateConsoleScreenBuffer( dwDesiredAccess, dwShareMode, dwFlags )
if @@m_CreateConsoleScreenBuffer == nil
@@m_CreateConsoleScreenBuffer = Win32API.new( "kernel32", "CreateConsoleScreenBuffer", ['l', 'l', 'p', 'l', 'p'], 'l' )
end
@@m_CreateConsoleScreenBuffer.call( dwDesiredAccess, dwShareMode,
nil, dwFlags, nil )
end
def FillConsoleOutputAttribute( hConsoleOutput, wAttribute, nLength,
col, row )
if @@m_FillConsoleOutputAttribute == nil
@@m_FillConsoleOutputAttribute = Win32API.new( "kernel32", "FillConsoleOutputAttribute", ['l', 'i', 'l', 'l', 'p'], 'l' )
end
dwWriteCoord = (row << 16) + col
lpNumberOfAttrsWritten = ' ' * 4
@@m_FillConsoleOutputAttribute.call( hConsoleOutput, wAttribute,
nLength, dwWriteCoord,
lpNumberOfAttrsWritten )
return lpNumberOfAttrsWritten.unpack('L')
end
def FillConsoleOutputCharacter( hConsoleOutput, cCharacter, nLength,
col, row )
if @@m_FillConsoleOutputCharacter == nil
@@m_FillConsoleOutputCharacter = Win32API.new( "kernel32", "FillConsoleOutputCharacter", ['l', 'i', 'l', 'l', 'p'], 'l' )
end
dwWriteCoord = (row << 16) + col
lpNumberOfAttrsWritten = ' ' * 4
@@m_FillConsoleOutputCharacter.call( hConsoleOutput, cCharacter,
nLength, dwWriteCoord,
lpNumberOfAttrsWritten )
return lpNumberOfAttrsWritten.unpack('L')
end
def FlushConsoleInputBuffer( hConsoleInput )
if @@m_FlushConsoleInputBuffer == nil
@@m_FlushConsoleInputBuffer = Win32API.new( "kernel32",
"FillConsoleInputBuffer",
['l'], 'l' )
end
@@m_FlushConsoleInputBuffer.call( hConsoleInput )
end
def FreeConsole()
if @@m_FreeConsole == nil
@@m_FreeConsole = Win32API.new( "kernel32", "FreeConsole", [], 'l' )
end
@@m_FreeConsole.call()
end
def GenerateConsoleCtrlEvent( dwCtrlEvent, dwProcessGroupId )
if @@m_GenerateConsoleCtrlEvent == nil
@@m_GenerateConsoleCtrlEvent = Win32API.new( "kernel32", "GenerateConsoleCtrlEvent", ['l', 'l'], 'l' )
end
@@m_GenerateConsoleCtrlEvent.call( dwCtrlEvent, dwProcessGroupId )
end
def GetConsoleCP()
if @@m_GetConsoleCP == nil
@@m_GetConsoleCP = Win32API.new( "kernel32", "GetConsoleCP",
[], 'l' )
end
@@m_GetConsoleCP.call()
end
def GetConsoleCursorInfo( hConsoleOutput )
if @@m_GetConsoleCursorInfo == nil
@@m_GetConsoleCursorInfo = Win32API.new( "kernel32",
"GetConsoleCursorInfo",
['l', 'p'], 'l' )
end
lpConsoleCursorInfo = ' ' * 8
@@m_GetConsoleCursorInfo.call( hConsoleOutput, lpConsoleCursorInfo )
return lpConsoleCursorInfo.unpack('LL')
end
def GetConsoleMode( hConsoleHandle )
if @@m_GetConsoleMode == nil
@@m_GetConsoleMode = Win32API.new( "kernel32", "GetConsoleMode",
['l', 'p'], 'l' )
end
lpMode = ' ' * 4
@@m_GetConsoleMode.call( hConsoleHandle, lpMode )
return lpMode.unpack('L')
end
def GetConsoleOutputCP()
if @@m_GetConsoleOutputCP == nil
@@m_GetConsoleOutputCP = Win32API.new( "kernel32",
"GetConsoleOutputCP", [], 'l' )
end
@@m_GetConsoleOutputCP.call()
end
def GetConsoleScreenBufferInfo( hConsoleOutput )
if @@m_GetConsoleScreenBufferInfo == nil
@@m_GetConsoleScreenBufferInfo = Win32API.new( "kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'l' )
end
lpBuffer = ' ' * 22
@@m_GetConsoleScreenBufferInfo.call( hConsoleOutput, lpBuffer )
return lpBuffer.unpack('SSSSSssssSS')
end
def GetConsoleTitle()
if @@m_GetConsoleTitle == nil
@@m_GetConsoleTitle = Win32API.new( "kernel32", "GetConsoleTitle",
['p', 'l'], 'l' )
end
nSize = 120
lpConsoleTitle = ' ' * nSize
@@m_GetConsoleTitle.call( lpConsoleTitle, nSize )
return lpConsoleTitle.strip
end
def GetConsoleWindow()
if @@m_GetConsoleWindow == nil
@@m_GetConsoleWindow = Win32API.new( "kernel32", "GetConsoleWindow",
[], 'l' )
end
@@m_GetConsoleWindow.call()
end
def GetLargestConsoleWindowSize( hConsoleOutput )
if @@m_GetLargestConsoleWindowSize == nil
@@m_GetLargestConsoleWindowSize = Win32API.new( "kernel32", "GetLargestConsoleWindowSize", ['l'], 'l' )
end
coord = @@m_GetLargestConsoleWindowSize.call( hConsoleOutput )
x = coord >> 16
y = coord & 0x0000ffff
return [x,y]
end
def GetNumberOfConsoleInputEvents( hConsoleInput )
if @@m_GetNumberOfConsoleInputEvents == nil
@@m_GetNumberOfConsoleInputEvents = Win32API.new( "kernel32", "GetNumberOfConsoleInputEvents", ['l', 'p'], 'l' )
end
lpcNumberOfEvents = 0
@@m_GetNumberOfConsoleInputEvents.call( hConsoleInput,
lpcNumberOfEvents )
return lpcNumberOfEvents
end
def GetNumberOfConsoleMouseButtons( )
if @@m_GetNumberOfConsoleMouseButtons == nil
@@m_GetNumberOfConsoleMouseButtons = Win32API.new( "kernel32", "GetNumberOfConsoleMouseButtons", ['p'], 'l' )
end
lpNumberOfMouseButtons = 0
@@m_GetNumberOfConsoleMouseButtons.call( lpNumberOfMouseButtons )
return lpNumberOfMouseButtons
end
def GetStdHandle( nStdHandle )
if @@m_GetStdHandle == nil
@@m_GetStdHandle = Win32API.new( "kernel32", "GetStdHandle",
['l'], 'l' )
end
@@m_GetStdHandle.call( nStdHandle )
end
# <> : This is not an actual API function, just a concept description in the SDK.
def PeekConsoleInput( hConsoleInput )
if @@m_PeekConsoleInput == nil
@@m_PeekConsoleInput = Win32API.new( "kernel32", "PeekConsoleInput",
['l', 'p', 'l', 'p'], 'l' )
end
lpNumberOfEventsRead = ' ' * 4
lpBuffer = ' ' * 20
nLength = 20
@@m_PeekConsoleInput.call( hConsoleInput, lpBuffer, nLength,
lpNumberOfEventsRead )
type = lpBuffer.unpack('s')[0]
case type
when KEY_EVENT
return lpBuffer.unpack('sSSSSCS')
when MOUSE_EVENT
return lpBuffer.unpack('sSSSS')
when WINDOW_BUFFER_SIZE_EVENT
return lpBuffer.unpack('sS')
when MENU_EVENT
return lpBuffer.unpack('sS')
when FOCUS_EVENT
return lpBuffer.unpack('sS')
else
return []
end
end
def ReadConsole( hConsoleInput, lpBuffer, nNumberOfCharsToRead )
if @@m_ReadConsole == nil
@@m_ReadConsole = Win32API.new( "kernel32", "ReadConsole",
['l', 'p', 'l', 'p', 'p'], 'l' )
end
lpBuffer = ' ' * nNumberOfCharsToRead unless lpBuffer
lpNumberOfCharsRead = ' ' * 4
lpReserved = ' ' * 4
@@m_ReadConsole.call( hConsoleInput, lpBuffer, nNumberOfCharsToRead,
lpNumberOfCharsRead, lpReserved )
return lpNumberOfCharsRead.unpack('L')
end
def ReadConsoleInput( hConsoleInput )
if @@m_ReadConsoleInput == nil
@@m_ReadConsoleInput = Win32API.new( "kernel32", "ReadConsoleInput",
['l', 'p', 'l', 'p'], 'l' )
end
lpNumberOfEventsRead = ' ' * 4
lpBuffer = ' ' * 20
nLength = 20
@@m_ReadConsoleInput.call( hConsoleInput, lpBuffer, nLength,
lpNumberOfEventsRead )
type = lpBuffer.unpack('s')[0]
case type
when KEY_EVENT
return lpBuffer.unpack('sSSSSCS')
when MOUSE_EVENT
return lpBuffer.unpack('sSSSS')
when WINDOW_BUFFER_SIZE_EVENT
return lpBuffer.unpack('sS')
when MENU_EVENT
return lpBuffer.unpack('sS')
when FOCUS_EVENT
return lpBuffer.unpack('sS')
else
return []
end
end
def ReadConsoleOutput( hConsoleOutput, lpBuffer, cols, rows,
bufx, bufy, left, top, right, bottom )
if @@m_ReadConsoleOutput == nil
@@m_ReadConsoleOutput = Win32API.new( "kernel32",
"ReadConsoleOutput",
['l', 'p', 'l', 'l', 'p'], 'l' )
end
dwBufferSize = cols * rows * 4
lpBuffer = ' ' * dwBufferSize
dwBufferCoord = (bufy << 16) + bufx
lpReadRegion = [ left, top, right, bottom ].pack('ssss')
@@m_ReadConsoleOutput.call( hConsoleOutput, lpBuffer, dwBufferSize,
dwBufferCoord, lpReadRegion )
end
def ReadConsoleOutputAttribute( hConsoleOutput, nLength, col, row )
if @@m_ReadConsoleOutputAttribute == nil
@@m_ReadConsoleOutputAttribute = Win32API.new( "kernel32", "ReadConsoleOutputAttribute", ['l', 'p', 'l', 'l', 'p'], 'l' )
end
lpAttribute = ' ' * nLength
dwReadCoord = (row << 16) + col
lpNumberOfAttrsRead = ' ' * 4
@@m_ReadConsoleOutputAttribute.call( hConsoleOutput, lpAttribute,
nLength, dwReadCoord,
lpNumberOfAttrsRead )
return lpAttribute
end
def ReadConsoleOutputCharacter( hConsoleOutput, lpCharacter, nLength,
col, row )
if @@m_ReadConsoleOutputCharacter == nil
@@m_ReadConsoleOutputCharacter = Win32API.new( "kernel32", "ReadConsoleOutputCharacter", ['l', 'p', 'l', 'l', 'p'], 'l' )
end
dwReadCoord = (row << 16) + col
lpNumberOfCharsRead = ' ' * 4
@@m_ReadConsoleOutputCharacter.call( hConsoleOutput, lpCharacter,
nLength, dwReadCoord,
lpNumberOfCharsRead )
return lpNumberOfCharsRead.unpack('L')
end
def ScrollConsoleScreenBuffer( hConsoleOutput,
left1, top1, right1, bottom1,
col, row, char, attr,
left2, top2, right2, bottom2 )
if @@m_ScrollConsoleScreenBuffer == nil
@@m_ScrollConsoleScreenBuffer = Win32API.new( "kernel32", "ScrollConsoleScreenBuffer", ['l', 'p', 'p', 'l', 'p'], 'l' )
end
lpScrollRectangle = [left1, top1, right1, bottom1].pack('ssss')
lpClipRectangle = [left2, top2, right2, bottom2].pack('ssss')
dwDestinationOrigin = (row << 16) + col
lpFill = [char, attr].pack('ss')
@@m_ScrollConsoleScreenBuffer.call( hConsoleOutput, lpScrollRectangle,
lpClipRectangle,
dwDestinationOrigin, lpFill )
end
def SetConsoleActiveScreenBuffer( hConsoleOutput )
if @@m_SetConsoleActiveScreenBuffer == nil
@@m_SetConsoleActiveScreenBuffer = Win32API.new( "kernel32", "SetConsoleActiveScreenBuffer", ['l'], 'l' )
end
@@m_SetConsoleActiveScreenBuffer.call( hConsoleOutput )
end
# <>: Will probably not be implemented.
def SetConsoleCP( wCodePageID )
if @@m_SetConsoleCP == nil
@@m_SetConsoleCP = Win32API.new( "kernel32", "SetConsoleCP",
['l'], 'l' )
end
@@m_SetConsoleCP.call( wCodePageID )
end
def SetConsoleCursorInfo( hConsoleOutput, col, row )
if @@m_SetConsoleCursorInfo == nil
@@m_SetConsoleCursorInfo = Win32API.new( "kernel32",
"SetConsoleCursorInfo",
['l', 'p'], 'l' )
end
lpConsoleCursorInfo = [size,visi].pack('LL')
@@m_SetConsoleCursorInfo.call( hConsoleOutput, lpConsoleCursorInfo )
end
def SetConsoleCursorPosition( hConsoleOutput, col, row )
if @@m_SetConsoleCursorPosition == nil
@@m_SetConsoleCursorPosition = Win32API.new( "kernel32", "SetConsoleCursorPosition", ['l', 'p'], 'l' )
end
dwCursorPosition = (row << 16) + col
@@m_SetConsoleCursorPosition.call( hConsoleOutput, dwCursorPosition )
end
def SetConsoleMode( hConsoleHandle, lpMode )
if @@m_SetConsoleMode == nil
@@m_SetConsoleMode = Win32API.new( "kernel32", "SetConsoleMode",
['l', 'p'], 'l' )
end
@@m_SetConsoleMode.call( hConsoleHandle, lpMode )
end
def SetConsoleOutputCP( wCodePageID )
if @@m_SetConsoleOutputCP == nil
@@m_SetConsoleOutputCP = Win32API.new( "kernel32",
"GetConsoleOutputCP",
['l'], 'l' )
end
@@m_SetConsoleOutputCP.call( wCodePageID )
end
def SetConsoleScreenBufferSize( hConsoleOutput, col, row )
if @@m_SetConsoleScreenBufferSize == nil
@@m_SetConsoleScreenBufferSize = Win32API.new( "kernel32", "SetConsoleScreenBufferSize", ['l', 'l'], 'l' )
end
dwSize = (row << 16) + col
@@m_SetConsoleScreenBufferSize.call( hConsoleOutput, dwSize )
end
def SetConsoleTextAttribute( hConsoleOutput, wAttributes )
if @@m_SetConsoleTextAttribute == nil
@@m_SetConsoleTextAttribute = Win32API.new( "kernel32", "SetConsoleTextAttribute", ['l', 'i'], 'l' )
end
@@m_SetConsoleTextAttribute.call( hConsoleOutput, wAttributes )
end
def SetConsoleTitle( lpConsoleTitle )
if @@m_SetConsoleTitle == nil
@@m_SetConsoleTitle = Win32API.new( "kernel32", "SetConsoleTitle",
['p'], 'l' )
end
@@m_SetConsoleTitle.call( lpConsoleTitle )
end
def SetConsoleWindowInfo( hConsoleOutput, bAbsolute,
left, top, right, bottom )
if @@m_SetConsoleWindowInfo == nil
@@m_SetConsoleWindowInfo = Win32API.new( "kernel32",
"SetConsoleWindowInfo",
['l', 'l', 'p'], 'l' )
end
lpConsoleWindow = [ left, top, right, bottom ].pack('ssss')
@@m_SetConsoleWindowInfo.call( hConsoleOutput, bAbsolute,
lpConsoleWindow )
end
def SetStdHandle( nStdHandle, hHandle )
if @@m_SetStdHandle == nil
@@m_SetStdHandle = Win32API.new( "kernel32", "SetStdHandle",
['l', 'l'], 'l' )
end
@@m_SetStdHandle.call( nStdHandle, hHandle )
end
def WriteConsole( hConsoleOutput, lpBuffer )
if @@m_WriteConsole == nil
@@m_WriteConsole = Win32API.new( "kernel32", "WriteConsole",
['l', 'p', 'l', 'p', 'p'], 'l' )
end
nNumberOfCharsToWrite = lpBuffer.length()
lpNumberOfCharsWritten = ' ' * 4
lpReserved = ' ' * 4
@@m_WriteConsole.call( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
lpNumberOfCharsWritten, lpReserved )
return lpNumberOfCharsWritten
end
def WriteConsoleInput( hConsoleInput, lpBuffer )
if @@m_WriteConsoleInput == nil
@@m_WriteConsoleInput = Win32API.new( "kernel32", "WriteConsoleInput", ['l', 'p', 'l', 'p'], 'l' )
end
@@m_WriteConsoleInput.call( hConsoleInput, lpBuffer, nLength,
lpNumberOfEventsWritten )
end
# @@ Todo: Test this
def WriteConsoleOutput( hConsoleOutput, buffer, cols, rows,
bufx, bufy, left, top, right, bottom )
if @@m_WriteConsoleOutput == nil
@@m_WriteConsoleOutput = Win32API.new( "kernel32", "WriteConsoleOutput", ['l', 'p', 'l', 'l', 'p'], 'l' )
end
lpBuffer = buffer.flatten.pack('ss' * buffer.length() * 2)
dwBufferSize = (buffer.length() << 16) + 2
dwBufferCoord = (row << 16) + col
lpWriteRegion = [ left, top, right, bottom ].pack('ssss')
@@m_WriteConsoleOutput.call( hConsoleOutput, lpBuffer, dwBufferSize,
dwBufferCoord, lpWriteRegion )
end
def WriteConsoleOutputAttribute( hConsoleOutput, lpAttribute, col, row )
if @@m_WriteConsoleOutputAttribute == nil
@@m_WriteConsoleOutputAttribute = Win32API.new( "kernel32", "WriteConsoleOutputAttribute", ['l', 'p', 'l', 'l', 'p'], 'l' )
end
nLength = lpAttribute.length()
dwWriteCoord = (row << 16) + col
lpNumberOfAttrsWritten = ' ' * 4
@@m_WriteConsoleOutputAttribute.call( hConsoleOutput, lpAttribute,
nLength, dwWriteCoord,
lpNumberOfAttrsWritten )
return lpNumberOfAttrsWritten.unpack('L')
end
def WriteConsoleOutputCharacter( hConsoleOutput, lpCharacter, col, row )
if @@m_WriteConsoleOutputCharacter == nil
@@m_WriteConsoleOutputCharacter = Win32API.new( "kernel32", "WriteConsoleOutputCharacter", ['l', 'p', 'l', 'l', 'p'], 'l' )
end
nLength = lpCharacter.length()
dwWriteCoord = (row << 16) + col
lpNumberOfCharsWritten = ' ' * 4
@@m_WriteConsoleOutputCharacter.call( hConsoleOutput, lpCharacter,
nLength, dwWriteCoord,
lpNumberOfCharsWritten )
return lpNumberOfCharsWritten.unpack('L')
end
end
end
end # rescue
module Win32
class Console
VERSION = '1.0'
include Win32::Console::Constants
def initialize( t = nil )
if t and ( t == STD_INPUT_HANDLE or t == STD_OUTPUT_HANDLE or
t == STD_ERROR_HANDLE )
@handle = API.GetStdHandle( t )
else
param1 = GENERIC_READ | GENERIC_WRITE
param2 = FILE_SHARE_READ | FILE_SHARE_WRITE
@handle = API.CreateConsoleScreenBuffer( param1, param2,
CONSOLE_TEXTMODE_BUFFER )
end
end
def Display
return API.SetConsoleActiveScreenBuffer(@handle)
end
def Select(type)
return API.SetStdHandle(type,@handle)
end
def Title(title = nil)
if title
return API.SetConsoleTitle(title)
else
return API.GetConsoleTitle()
end
end
def WriteChar(s, col, row)
API.WriteConsoleOutputCharacter( @handle, s, col, row )
end
def ReadChar(size, col, row)
buffer = ' ' * size
if API.ReadConsoleOutputCharacter( @handle, buffer, size, col, row )
return buffer
else
return nil
end
end
def WriteAttr(attr, col, row)
API.WriteConsoleOutputAttribute( @handle, attr, col, row )
end
def ReadAttr(size, col, row)
x = API.ReadConsoleOutputAttribute( @handle, size, col, row )
return x.unpack('c'*size)
end
def Cursor(*t)
col, row, size, visi = t
if col
row = -1 if !row
if col < 0 or row < 0
curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
col = curr_col if col < 0
row = curr_row if row < 0
end
API.SetConsoleCursorPosition( @handle, col, row )
if size and visi
curr_size, curr_visi = API.GetConsoleCursorInfo( @handle )
size = curr_size if size < 0
visi = curr_visi if visi < 0
size = 1 if size < 1
size = 99 if size > 99
API.SetConsoleCursorInfo( @handle, size, visi )
end
else
d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
curr_size, curr_visi = API.GetConsoleCursorInfo( @handle )
return [ curr_col, curr_row, curr_size, curr_visi ]
end
end
def Write(s)
API.WriteConsole( @handle, s )
end
def ReadRect( left, top, right, bottom )
col = right - left + 1
row = bottom - top + 1
size = col * row
buffer = ' ' * size * 4
if API.ReadConsoleOutput( @handle, buffer, col, row, 0, 0,
left, top, right, bottom )
#return buffer.unpack('US'*size) # for unicode
return buffer.unpack('axS'*size) # for ascii
else
return nil
end
end
def WriteRect( buffer, left, top, right, bottom )
col = right - left + 1
row = bottom - top + 1
API.WriteConsoleOutput( @handle, buffer, col, row, 0, 0,
left, top, right, bottom )
end
def Scroll( left1, top1, right1, bottom1,
col, row, char, attr,
left2, top2, right2, bottom2 )
API.ScrollConsoleScreenBuffer(@handle, left1, top1, right1, bottom1,
col, row, char, attr,
left2, top2, right2, bottom2)
end
def MaxWindow(flag = nil)
if !flag
info = API.GetConsoleScreenBufferInfo(@handle)
return info[9], info[10]
else
return API.GetLargestConsoleWindowSize(@handle)
end
end
def Info()
return API.GetConsoleScreenBufferInfo( @handle )
end
def GetEvents()
return API.GetNumberOfConsoleInputEvents(@handle)
end
def Flush()
return API.FlushConsoleInputBuffer(@handle)
end
def InputChar(number = nil)
number = 1 unless number
buffer = ' ' * number
if API.ReadConsole(@handle, buffer, number) == number
return buffer
else
return nil
end
end
def Input()
API.ReadConsoleInput(@handle)
end
def PeekInput()
API.PeekConsoleInput(@handle)
end
def Mode(mode = nil)
if mode
mode = mode.pack('L') if mode === Array
API.SetConsoleMode(@handle, mode)
else
return API.GetConsoleMode(@handle)
end
end
def WriteInput(*t)
API.WriteConsoleInput(@handle, *t)
end
def Attr(*attr)
if attr.size > 0
API.SetConsoleTextAttribute( @handle, attr[0] )
else
info = API.GetConsoleScreenBufferInfo( @handle )
return info[4]
end
end
def Size(*t)
if t.size == 0
col, row = API.GetConsoleScreenBufferInfo(@handle )
return [col, row]
else
row = -1 if !t[1]
col = -1 if !t[0]
if col < 0 or row < 0
curr_col, curr_row = Size()
col = curr_col if col < 0
row = curr_row if row < 0
end
API.SetConsoleScreenBufferSize(@handle, row, col)
end
end
def Window(*t)
if t.size != 5
info = API.GetConsoleScreenBufferInfo( @handle )
return info[5..8]
else
API.SetConsoleWindowInfo(@handle, t[0], t[1], t[2], t[3], t[4])
end
end
def FillAttr(attr, number = 1, col = -1, row = -1)
if col < 0 or row < 0
d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
col = curr_col if col < 0
row = curr_row if row < 0
end
API.FillConsoleOutputAttribute(@handle, attr, number, col, row)
end
def FillChar(char, number, col = -1, row = -1)
if col < 0 or row < 0
d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
col = curr_col if col < 0
row = curr_row if row < 0
end
API.FillConsoleOutputCharacter(@handle, char[0], number, col, row)
end
def Cls()
attr = ATTR_NORMAL
x, y = Size()
left, top, right , bottom = Window()
vx = right - left
vy = bottom - top
FillChar(' ', x*y, 0, 0)
FillAttr(attr, x*y, 0, 0)
Cursor(0,0)
Window(1,0,0,vx,vy)
end
def Console.Free()
API.FreeConsole()
end
def Console.Alloc()
API.AllocConsole()
end
def Console.MouseButtons()
API.GetNumberOfConsoleMouseButtons()
end
def Console.InputCP(codepage=nil)
if codepage
API.SetConsoleCP(codepage)
else
return API.GetConsoleCP()
end
end
def Console.OutputCP(codepage=nil)
if codepage
API.SetConsoleOutputCP(codepage)
else
return API.GetConsoleOutputCP()
end
end
def Console.GenerateCtrlEvent( type=nil, pid=nil )
type = API.constant('CTRL_C_EVENT') if type == nil
pid = 0 if pid == nil
API.GenerateConsoleCtrlEvent(type, pid)
end
end
end
FG_BLACK = 0
FG_BLUE = Win32::Console::API.constant("FOREGROUND_BLUE")
FG_LIGHTBLUE = Win32::Console::API.constant("FOREGROUND_BLUE")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_RED = Win32::Console::API.constant("FOREGROUND_RED")
FG_LIGHTRED = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_GREEN = Win32::Console::API.constant("FOREGROUND_GREEN")
FG_LIGHTGREEN = Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_MAGENTA = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_BLUE")
FG_LIGHTMAGENTA = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_BLUE")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_CYAN = Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_BLUE")
FG_LIGHTCYAN = Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_BLUE")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_BROWN = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_GREEN")
FG_YELLOW = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
FG_GRAY = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_BLUE")
FG_WHITE = Win32::Console::API.constant("FOREGROUND_RED")|
Win32::Console::API.constant("FOREGROUND_GREEN")|
Win32::Console::API.constant("FOREGROUND_BLUE")|
Win32::Console::API.constant("FOREGROUND_INTENSITY")
BG_BLACK = 0
BG_BLUE = Win32::Console::API.constant("BACKGROUND_BLUE")
BG_LIGHTBLUE = Win32::Console::API.constant("BACKGROUND_BLUE")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_RED = Win32::Console::API.constant("BACKGROUND_RED")
BG_LIGHTRED = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_GREEN = Win32::Console::API.constant("BACKGROUND_GREEN")
BG_LIGHTGREEN = Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_MAGENTA = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_BLUE")
BG_LIGHTMAGENTA = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_BLUE")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_CYAN = Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_BLUE")
BG_LIGHTCYAN = Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_BLUE")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_BROWN = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_GREEN")
BG_YELLOW = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
BG_GRAY = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_BLUE")
BG_WHITE = Win32::Console::API.constant("BACKGROUND_RED")|
Win32::Console::API.constant("BACKGROUND_GREEN")|
Win32::Console::API.constant("BACKGROUND_BLUE")|
Win32::Console::API.constant("BACKGROUND_INTENSITY")
ATTR_NORMAL = FG_GRAY | BG_BLACK
ATTR_INVERSE = FG_BLACK | BG_GRAY
include Win32::Console::Constants
|