|
|
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::ANSI
#
# Copyright 2004 - Gonzalo Garramuno
# Licensed under GNU General Public License or Perl's Artistic License
#
# Based on Perl's Win32::Console::ANSI
# Copyright (c) 2003 Jean-Louis Morel
# Licensed under GNU General Public License or Perl's Artistic License
#
require "win32/Console"
module Win32
class Console
module ANSI
class IO < IO
VERSION = '0.05'
DEBUG = nil
require "win32/registry"
include Win32::Console::Constants
# @todo: encode is another perl module
EncodeOk = false
# Retrieving the codepages
cpANSI = nil
Win32::Registry::HKEY_LOCAL_MACHINE.open('SYSTEM\CurrentControlSet\Control\Nls\CodePage' ) { |reg|
cpANSI = reg['ACP']
}
STDERR.puts "Unable to read Win codepage #{cpANSI}" if DEBUG && !cpANSI
cpANSI = 'cp'+(cpANSI ? cpANSI : '1252') # Windows codepage
OEM = Win32::Console::OutputCP()
cpOEM = 'cp' + OEM.to_s # DOS codepage
@@cp = cpANSI + cpOEM
STDERR.puts "EncodeOk=#{EncodeOk} cpANSI=#{cpANSI} "+
"cpOEM=#{cpOEM}" if DEBUG
@@color = { 30 => 0, # black foreground
31 => FOREGROUND_RED, # red foreground
32 => FOREGROUND_GREEN, # green foreground
33 => FOREGROUND_RED|FOREGROUND_GREEN, # yellow foreground
34 => FOREGROUND_BLUE, # blue foreground
35 => FOREGROUND_BLUE|FOREGROUND_RED, # magenta foreground
36 => FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan foreground
37 => FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE, # white foreground
40 => 0, # black background
41 => BACKGROUND_RED, # red background
42 => BACKGROUND_GREEN, # green background
43 => BACKGROUND_RED|BACKGROUND_GREEN, # yellow background
44 => BACKGROUND_BLUE, # blue background
45 => BACKGROUND_BLUE|BACKGROUND_RED, # magenta background
46 => BACKGROUND_BLUE|BACKGROUND_GREEN, # cyan background
47 => BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE, # white background
}
def initialize
super(1,'w')
@Out = Win32::Console.new(STD_OUTPUT_HANDLE)
@x = @y = 0 # to save cursor position
@foreground = 7
@background = 0
@bold =
@underline =
@revideo =
@concealed = nil
@conv = 1 # char conversion by default
end
def write(*s)
s.each { |x|
_PrintString(x)
}
end
private
def _PrintString(t)
s = t.dup
while s != ''
if s.sub!( /([^\e]*)?\e([\[\(])([0-9\;\=]*)([a-zA-Z@])(.*)/s,'\5')
@Out.Write((_conv("#$1")))
if $2 == '['
case $4
when 'm' # ESC[#;#;....;#m Set display attributes
attributs = $3.split(';')
attributs.push(nil) unless attributs # ESC[m == ESC[;m ==...==ESC[0m
for attr in attributs
atv = attr.to_i
if atv > 0
if atv == 1
@bold = 1
elsif atv == 21
@bold = nil
elsif atv == 4
@underline = 1
elsif atv == 24
@underline = nil
elsif atv == 7
@revideo = 1
elsif atv == 27
@revideo = nil
elsif atv == 8
@concealed = 1
elsif atv == 28
@concealed = nil
elsif atv >= 30 and atv <= 37
@foreground = atv - 30
elsif atv >=40 and atv <=47
@background = atv - 40
end
else # ESC[0m reset
@foreground = 7
@background = 0
@bold =
@underline =
@revideo =
@concealed = nil
end
end
if @revideo
attribut = @@color[40+@foreground] |
@@color[30+@background]
else
attribut = @@color[30+@foreground] |
@@color[40+@background]
end
attribut |= FOREGROUND_INTENSITY if @bold
attribut |= BACKGROUND_INTENSITY if @underline
@Out.Attr(attribut)
when 'J'
if !$3 or $3 == '' # ESC[0J from cursor to end of display
info = @Out.Info()
s = ' ' * ((info[1]-info[3]-1)*info[0]+info[0]-info[2]-1)
@Out.WriteChar(s, info[2], info[3])
@Out.Cursor(info[2], info[3])
elsif $3 == '1' # ESC[1J erase from start to cursor.
info = @Out.Info()
s = ' ' * (info[3]*info[0]+info[2]+1)
@Out.WriteChar(s, 0, 0)
@Out.Cursor(info[2], info[3])
elsif $3 == '2' # ESC[2J Clear screen and home cursor
@Out.Cls()
@Out.Cursor(0, 0)
else
STDERR.print "\e#$2#$3#$4" if DEBUG # if ESC-code not implemented
end
when 'K'
info = @Out.Info()
if !$3 or $3 == '' # ESC[0K Clear to end of line
s = ' ' * (info[7]-info[2]+1)
@Out.Write(s)
@Out.Cursor(info[2], info[3])
elsif $3=='1' # ESC[1K Clear from start of line to cursor
s = ' '*(info[2]+1)
@Out.WriteChar(s, 0, info[3])
@Out.Cursor(info[2], info[3])
elsif $3=='2' # ESC[2K Clear whole line.
s = ' '* info[0]
@Out.WriteChar(s, 0, info[3])
@Out.Cursor(info[2], info[3])
end
when 'L' # ESC[#L Insert # blank lines.
n = $3 == ''? 1 : $3.to_i # ESC[L == ESC[1L
info = @Out.Info()
@Out.Scroll(0, info[3], info[0]-1, info[1]-1,
0, info[3] + n.to_i,
' '[0], @Out.Attr(),
0, 0, 10000, 10000)
@Out.Cursor(info[2], info[3])
when 'M' # ESC[#M Delete # line.
n = $3 == ''? 1 : $3.to_i # ESC[M == ESC[1M
info = @Out.Info();
@Out.Scroll(0, info[3]+n, info[0]-1, info[1]-1,
0, info[3],
' '[0], @Out.Attr(),
0, 0, 10000, 10000)
@Out.Cursor(info[2], info[3])
when 'P' # ESC[#P Delete # characters.
n = $3 == ''? 1 : $3.to_i # ESC[P == ESC[1P
info = @Out.Info()
n = info[0]-info[2] if info[2]+n > info[0]-1
@Out.Scroll(info[2]+n, info[3] , info[0]-1, info[3],
info[2], info[3],
' '[0], @Out.Attr(),
0, 0, 10000, 10000)
s = ' ' * n
@Out.Cursor(info[0]-n, info[3])
@Out.Write(s)
@Out.Cursor(info[2], info[3])
when '@' # ESC[#@ Insert # blank Characters
s = ' ' * $3.to_i
info = @Out.Info()
s << @Out.ReadChar(info[7]-info[2]+1, info[2], info[3])
s = s[0..-($3.to_i)]
@Out.Write(s);
@Out.Cursor(info[2], info[3])
when 'A' # ESC[#A Moves cursor up # lines
(x, y) = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[A == ESC[1A
@Out.Cursor(x, y-n)
when 'B' # ESC[#B Moves cursor down # lines
(x, y) = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[B == ESC[1B
@Out.Cursor(x, y+n)
when 'C' # ESC[#C Moves cursor forward # spaces
(x, y) = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[C == ESC[1C
@Out.Cursor(x+n, y)
when 'D' # ESC[#D Moves cursor back # spaces
(x, y) = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[D == ESC[1D
@Out.Cursor(x-n, y)
when 'E' # ESC[#E Moves cursor down # lines, column 1.
x, y = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[E == ESC[1E
@Out.Cursor(0, y+n)
when 'F' # ESC[#F Moves cursor up # lines, column 1.
x, y = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[F == ESC[1F
@Out.Cursor(0, y-n)
when 'G' # ESC[#G Moves cursor column # in current row.
x, y = @Out.Cursor()
n = $3 == ''? 1 : $3.to_i; # ESC[G == ESC[1G
@Out.Cursor(n-1, y)
when 'f' # ESC[#;#f Moves cursor to line #, column #
y, x = $3.split(';')
x = 1 unless x # ESC[;5H == ESC[1;5H ...etc
y = 1 unless y
@Out.Cursor(x.to_i-1, y.to_i-1) # origin (0,0) in DOS console
when 'H' # ESC[#;#H Moves cursor to line #, column #
y, x = $3.split(';')
x = 1 unless x # ESC[;5H == ESC[1;5H ...etc
y = 1 unless y
@Out.Cursor(x.to_i-1, y.to_i-1) # origin (0,0) in DOS console
when 's' # ESC[s Saves cursor position for recall later
(@x, @y) = @Out.Cursor()
when 'u' # ESC[u Return to saved cursor position
@Out.Cursor(@x, @y)
else
STDERR.puts "\e#$2#$3#$4 not implemented" if DEBUG # ESC-code not implemented
end
else
case $4
when 'U' # ESC(U no mapping
@conv = nil
when 'K' # ESC(K mapping if it exist
@Out.OutputCP(OEM) # restore original codepage
@conv = 1
when 'X' # ESC(#X codepage **EXPERIMENTAL**
@conv = nil
@Out.OutputCP($3)
else
STDERR.puts "\e#$2#$3#$4 not implemented" if DEBUG # ESC-code not implemented
end
end
else
@Out.Write(_conv(s))
s=''
end
end
end
def _conv(s)
if @concealed
s.gsub!( /\S/,' ')
elsif @conv
if EncodeOk
from_to(s, cpANSI, cpOEM)
elsif @@cp == 'cp1252cp850' # WinLatin1 --> DOSLatin1
s.tr!("ÁāŁƁǁȁɁʁˁ́́ρЁсҁӁԁՁցׁفځہ܁݁ށ߁","?????????????????????????????ρ݁ǎԐҁӁށցׁс噞ꚁᅁƄЁ䔁")
elsif @@cp == 'cp1252cp437' # WinLatin1 --> DOSLatinUS
s.tr!("ÁāŁƁǁȁɁʁˁ́́ρЁсҁӁԁՁցׁفځہ܁݁ށ߁", "???????????????????????????????????????????????????????????????????ᅁ??????")
elsif @@cp == 'cp1250cp852' # WinLatin2 --> DOSLatin2
s.tr!("ÁāŁƁǁȁɁʁˁ́́ρЁсҁӁԁՁցׁفځہ܁݁ށ߁",
"??????????????????????ρ???????聵ƎӁցׁҁсՁ⊙ށ뚁݁ꁠDŽԁЁ偢" )
elsif @@cp == 'cp1251cp855' # WinCyrillic --> DOSCyrillic
s.tr!("ÁāŁƁǁȁɁʁˁ́́ρЁсҁӁԁՁցׁفځہ܁݁ށ߁",
"?????????????????????????????쁭ǁсӁՁׁ݁聫끬ƁЁҁԁց灪")
end
end
return s
end
end
# end print overloading
end
end
end
$stdout = Win32::Console::ANSI::IO.new()
|