PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/work/reference/console/lib/Win32/Console/ANSI.rb

http://github.com/rubyworks/ansi
Ruby | 305 lines | 266 code | 26 blank | 13 comment | 43 complexity | 53885882bfe055bf879c513e4bfc07db MD5 | raw file
Possible License(s): GPL-2.0
  1. #
  2. # Win32::Console::ANSI
  3. #
  4. # Copyright 2004 - Gonzalo Garramuno
  5. # Licensed under GNU General Public License or Perl's Artistic License
  6. #
  7. # Based on Perl's Win32::Console::ANSI
  8. # Copyright (c) 2003 Jean-Louis Morel <jl_morel@bribes.org>
  9. # Licensed under GNU General Public License or Perl's Artistic License
  10. #
  11. require "win32/Console"
  12. module Win32
  13. class Console
  14. module ANSI
  15. class IO < IO
  16. VERSION = '0.05'
  17. DEBUG = nil
  18. require "win32/registry"
  19. include Win32::Console::Constants
  20. # @todo: encode is another perl module
  21. EncodeOk = false
  22. # Retrieving the codepages
  23. cpANSI = nil
  24. Win32::Registry::HKEY_LOCAL_MACHINE.open('SYSTEM\CurrentControlSet\Control\Nls\CodePage' ) { |reg|
  25. cpANSI = reg['ACP']
  26. }
  27. STDERR.puts "Unable to read Win codepage #{cpANSI}" if DEBUG && !cpANSI
  28. cpANSI = 'cp'+(cpANSI ? cpANSI : '1252') # Windows codepage
  29. OEM = Win32::Console::OutputCP()
  30. cpOEM = 'cp' + OEM.to_s # DOS codepage
  31. @@cp = cpANSI + cpOEM
  32. STDERR.puts "EncodeOk=#{EncodeOk} cpANSI=#{cpANSI} "+
  33. "cpOEM=#{cpOEM}" if DEBUG
  34. @@color = { 30 => 0, # black foreground
  35. 31 => FOREGROUND_RED, # red foreground
  36. 32 => FOREGROUND_GREEN, # green foreground
  37. 33 => FOREGROUND_RED|FOREGROUND_GREEN, # yellow foreground
  38. 34 => FOREGROUND_BLUE, # blue foreground
  39. 35 => FOREGROUND_BLUE|FOREGROUND_RED, # magenta foreground
  40. 36 => FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan foreground
  41. 37 => FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE, # white foreground
  42. 40 => 0, # black background
  43. 41 => BACKGROUND_RED, # red background
  44. 42 => BACKGROUND_GREEN, # green background
  45. 43 => BACKGROUND_RED|BACKGROUND_GREEN, # yellow background
  46. 44 => BACKGROUND_BLUE, # blue background
  47. 45 => BACKGROUND_BLUE|BACKGROUND_RED, # magenta background
  48. 46 => BACKGROUND_BLUE|BACKGROUND_GREEN, # cyan background
  49. 47 => BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE, # white background
  50. }
  51. def initialize
  52. super(1,'w')
  53. @Out = Win32::Console.new(STD_OUTPUT_HANDLE)
  54. @x = @y = 0 # to save cursor position
  55. @foreground = 7
  56. @background = 0
  57. @bold =
  58. @underline =
  59. @revideo =
  60. @concealed = nil
  61. @conv = 1 # char conversion by default
  62. end
  63. def write(*s)
  64. s.each { |x|
  65. _PrintString(x)
  66. }
  67. end
  68. private
  69. def _PrintString(t)
  70. s = t.dup
  71. while s != ''
  72. if s.sub!( /([^\e]*)?\e([\[\(])([0-9\;\=]*)([a-zA-Z@])(.*)/s,'\5')
  73. @Out.Write((_conv("#$1")))
  74. if $2 == '['
  75. case $4
  76. when 'm' # ESC[#;#;....;#m Set display attributes
  77. attributs = $3.split(';')
  78. attributs.push(nil) unless attributs # ESC[m == ESC[;m ==...==ESC[0m
  79. for attr in attributs
  80. atv = attr.to_i
  81. if atv > 0
  82. if atv == 1
  83. @bold = 1
  84. elsif atv == 21
  85. @bold = nil
  86. elsif atv == 4
  87. @underline = 1
  88. elsif atv == 24
  89. @underline = nil
  90. elsif atv == 7
  91. @revideo = 1
  92. elsif atv == 27
  93. @revideo = nil
  94. elsif atv == 8
  95. @concealed = 1
  96. elsif atv == 28
  97. @concealed = nil
  98. elsif atv >= 30 and atv <= 37
  99. @foreground = atv - 30
  100. elsif atv >=40 and atv <=47
  101. @background = atv - 40
  102. end
  103. else # ESC[0m reset
  104. @foreground = 7
  105. @background = 0
  106. @bold =
  107. @underline =
  108. @revideo =
  109. @concealed = nil
  110. end
  111. end
  112. if @revideo
  113. attribut = @@color[40+@foreground] |
  114. @@color[30+@background]
  115. else
  116. attribut = @@color[30+@foreground] |
  117. @@color[40+@background]
  118. end
  119. attribut |= FOREGROUND_INTENSITY if @bold
  120. attribut |= BACKGROUND_INTENSITY if @underline
  121. @Out.Attr(attribut)
  122. when 'J'
  123. if !$3 or $3 == '' # ESC[0J from cursor to end of display
  124. info = @Out.Info()
  125. s = ' ' * ((info[1]-info[3]-1)*info[0]+info[0]-info[2]-1)
  126. @Out.WriteChar(s, info[2], info[3])
  127. @Out.Cursor(info[2], info[3])
  128. elsif $3 == '1' # ESC[1J erase from start to cursor.
  129. info = @Out.Info()
  130. s = ' ' * (info[3]*info[0]+info[2]+1)
  131. @Out.WriteChar(s, 0, 0)
  132. @Out.Cursor(info[2], info[3])
  133. elsif $3 == '2' # ESC[2J Clear screen and home cursor
  134. @Out.Cls()
  135. @Out.Cursor(0, 0)
  136. else
  137. STDERR.print "\e#$2#$3#$4" if DEBUG # if ESC-code not implemented
  138. end
  139. when 'K'
  140. info = @Out.Info()
  141. if !$3 or $3 == '' # ESC[0K Clear to end of line
  142. s = ' ' * (info[7]-info[2]+1)
  143. @Out.Write(s)
  144. @Out.Cursor(info[2], info[3])
  145. elsif $3=='1' # ESC[1K Clear from start of line to cursor
  146. s = ' '*(info[2]+1)
  147. @Out.WriteChar(s, 0, info[3])
  148. @Out.Cursor(info[2], info[3])
  149. elsif $3=='2' # ESC[2K Clear whole line.
  150. s = ' '* info[0]
  151. @Out.WriteChar(s, 0, info[3])
  152. @Out.Cursor(info[2], info[3])
  153. end
  154. when 'L' # ESC[#L Insert # blank lines.
  155. n = $3 == ''? 1 : $3.to_i # ESC[L == ESC[1L
  156. info = @Out.Info()
  157. @Out.Scroll(0, info[3], info[0]-1, info[1]-1,
  158. 0, info[3] + n.to_i,
  159. ' '[0], @Out.Attr(),
  160. 0, 0, 10000, 10000)
  161. @Out.Cursor(info[2], info[3])
  162. when 'M' # ESC[#M Delete # line.
  163. n = $3 == ''? 1 : $3.to_i # ESC[M == ESC[1M
  164. info = @Out.Info();
  165. @Out.Scroll(0, info[3]+n, info[0]-1, info[1]-1,
  166. 0, info[3],
  167. ' '[0], @Out.Attr(),
  168. 0, 0, 10000, 10000)
  169. @Out.Cursor(info[2], info[3])
  170. when 'P' # ESC[#P Delete # characters.
  171. n = $3 == ''? 1 : $3.to_i # ESC[P == ESC[1P
  172. info = @Out.Info()
  173. n = info[0]-info[2] if info[2]+n > info[0]-1
  174. @Out.Scroll(info[2]+n, info[3] , info[0]-1, info[3],
  175. info[2], info[3],
  176. ' '[0], @Out.Attr(),
  177. 0, 0, 10000, 10000)
  178. s = ' ' * n
  179. @Out.Cursor(info[0]-n, info[3])
  180. @Out.Write(s)
  181. @Out.Cursor(info[2], info[3])
  182. when '@' # ESC[#@ Insert # blank Characters
  183. s = ' ' * $3.to_i
  184. info = @Out.Info()
  185. s << @Out.ReadChar(info[7]-info[2]+1, info[2], info[3])
  186. s = s[0..-($3.to_i)]
  187. @Out.Write(s);
  188. @Out.Cursor(info[2], info[3])
  189. when 'A' # ESC[#A Moves cursor up # lines
  190. (x, y) = @Out.Cursor()
  191. n = $3 == ''? 1 : $3.to_i; # ESC[A == ESC[1A
  192. @Out.Cursor(x, y-n)
  193. when 'B' # ESC[#B Moves cursor down # lines
  194. (x, y) = @Out.Cursor()
  195. n = $3 == ''? 1 : $3.to_i; # ESC[B == ESC[1B
  196. @Out.Cursor(x, y+n)
  197. when 'C' # ESC[#C Moves cursor forward # spaces
  198. (x, y) = @Out.Cursor()
  199. n = $3 == ''? 1 : $3.to_i; # ESC[C == ESC[1C
  200. @Out.Cursor(x+n, y)
  201. when 'D' # ESC[#D Moves cursor back # spaces
  202. (x, y) = @Out.Cursor()
  203. n = $3 == ''? 1 : $3.to_i; # ESC[D == ESC[1D
  204. @Out.Cursor(x-n, y)
  205. when 'E' # ESC[#E Moves cursor down # lines, column 1.
  206. x, y = @Out.Cursor()
  207. n = $3 == ''? 1 : $3.to_i; # ESC[E == ESC[1E
  208. @Out.Cursor(0, y+n)
  209. when 'F' # ESC[#F Moves cursor up # lines, column 1.
  210. x, y = @Out.Cursor()
  211. n = $3 == ''? 1 : $3.to_i; # ESC[F == ESC[1F
  212. @Out.Cursor(0, y-n)
  213. when 'G' # ESC[#G Moves cursor column # in current row.
  214. x, y = @Out.Cursor()
  215. n = $3 == ''? 1 : $3.to_i; # ESC[G == ESC[1G
  216. @Out.Cursor(n-1, y)
  217. when 'f' # ESC[#;#f Moves cursor to line #, column #
  218. y, x = $3.split(';')
  219. x = 1 unless x # ESC[;5H == ESC[1;5H ...etc
  220. y = 1 unless y
  221. @Out.Cursor(x.to_i-1, y.to_i-1) # origin (0,0) in DOS console
  222. when 'H' # ESC[#;#H Moves cursor to line #, column #
  223. y, x = $3.split(';')
  224. x = 1 unless x # ESC[;5H == ESC[1;5H ...etc
  225. y = 1 unless y
  226. @Out.Cursor(x.to_i-1, y.to_i-1) # origin (0,0) in DOS console
  227. when 's' # ESC[s Saves cursor position for recall later
  228. (@x, @y) = @Out.Cursor()
  229. when 'u' # ESC[u Return to saved cursor position
  230. @Out.Cursor(@x, @y)
  231. else
  232. STDERR.puts "\e#$2#$3#$4 not implemented" if DEBUG # ESC-code not implemented
  233. end
  234. else
  235. case $4
  236. when 'U' # ESC(U no mapping
  237. @conv = nil
  238. when 'K' # ESC(K mapping if it exist
  239. @Out.OutputCP(OEM) # restore original codepage
  240. @conv = 1
  241. when 'X' # ESC(#X codepage **EXPERIMENTAL**
  242. @conv = nil
  243. @Out.OutputCP($3)
  244. else
  245. STDERR.puts "\e#$2#$3#$4 not implemented" if DEBUG # ESC-code not implemented
  246. end
  247. end
  248. else
  249. @Out.Write(_conv(s))
  250. s=''
  251. end
  252. end
  253. end
  254. def _conv(s)
  255. if @concealed
  256. s.gsub!( /\S/,' ')
  257. elsif @conv
  258. if EncodeOk
  259. from_to(s, cpANSI, cpOEM)
  260. elsif @@cp == 'cp1252cp850' # WinLatin1 --> DOSLatin1
  261. s.tr!("ÁāŁƁǁȁɁʁˁ́́΁ρЁсҁӁԁՁցׁ؁فځہ܁݁ށ߁","?????????????????????????????ρ݁󁨁ǎԐҁӁށցׁ؁с噞ꚁᅁƄЁ䔁")
  262. elsif @@cp == 'cp1252cp437' # WinLatin1 --> DOSLatinUS
  263. s.tr!("ÁāŁƁǁȁɁʁˁ́́΁ρЁсҁӁԁՁցׁ؁فځہ܁݁ށ߁", "???????????????????????????????????????????????????????????????????ᅁ??????")
  264. elsif @@cp == 'cp1250cp852' # WinLatin2 --> DOSLatin2
  265. s.tr!("ÁāŁƁǁȁɁʁˁ́́΁ρЁсҁӁԁՁցׁ؁فځہ܁݁ށ߁",
  266. "??????????????????????ρ???????񖁾聵ƎӁցׁҁсՁ⊙ށ뚁݁ꁠDŽ؁ԁЁ偢" )
  267. elsif @@cp == 'cp1251cp855' # WinCyrillic --> DOSCyrillic
  268. s.tr!("ÁāŁƁǁȁɁʁˁ́́΁ρЁсҁӁԁՁցׁ؁فځہ܁݁ށ߁",
  269. "?????????????????????????????쁭􁸁ǁсӁՁׁ݁聫끬󁷁ƁЁҁԁց؁灪")
  270. end
  271. end
  272. return s
  273. end
  274. end
  275. # end print overloading
  276. end
  277. end
  278. end
  279. $stdout = Win32::Console::ANSI::IO.new()