solutious-stella 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/CHANGES.txt +36 -0
  2. data/README.textile +162 -0
  3. data/Rakefile +88 -0
  4. data/bin/stella +12 -0
  5. data/bin/stella.bat +12 -0
  6. data/lib/daemonize.rb +56 -0
  7. data/lib/pcaplet.rb +180 -0
  8. data/lib/stella.rb +101 -0
  9. data/lib/stella/adapter/ab.rb +337 -0
  10. data/lib/stella/adapter/base.rb +106 -0
  11. data/lib/stella/adapter/httperf.rb +305 -0
  12. data/lib/stella/adapter/pcap_watcher.rb +221 -0
  13. data/lib/stella/adapter/proxy_watcher.rb +76 -0
  14. data/lib/stella/adapter/siege.rb +341 -0
  15. data/lib/stella/cli.rb +258 -0
  16. data/lib/stella/cli/agents.rb +73 -0
  17. data/lib/stella/cli/base.rb +55 -0
  18. data/lib/stella/cli/language.rb +18 -0
  19. data/lib/stella/cli/localtest.rb +78 -0
  20. data/lib/stella/cli/sysinfo.rb +16 -0
  21. data/lib/stella/cli/watch.rb +278 -0
  22. data/lib/stella/command/base.rb +40 -0
  23. data/lib/stella/command/localtest.rb +358 -0
  24. data/lib/stella/data/domain.rb +82 -0
  25. data/lib/stella/data/http.rb +131 -0
  26. data/lib/stella/logger.rb +84 -0
  27. data/lib/stella/response.rb +85 -0
  28. data/lib/stella/storable.rb +201 -0
  29. data/lib/stella/support.rb +276 -0
  30. data/lib/stella/sysinfo.rb +257 -0
  31. data/lib/stella/test/definition.rb +79 -0
  32. data/lib/stella/test/run/summary.rb +70 -0
  33. data/lib/stella/test/stats.rb +114 -0
  34. data/lib/stella/text.rb +64 -0
  35. data/lib/stella/text/resource.rb +38 -0
  36. data/lib/utils/crypto-key.rb +84 -0
  37. data/lib/utils/domainutil.rb +47 -0
  38. data/lib/utils/escape.rb +302 -0
  39. data/lib/utils/fileutil.rb +78 -0
  40. data/lib/utils/httputil.rb +266 -0
  41. data/lib/utils/mathutil.rb +15 -0
  42. data/lib/utils/stats.rb +88 -0
  43. data/lib/utils/textgraph.rb +267 -0
  44. data/lib/utils/timerutil.rb +58 -0
  45. data/lib/win32/Console.rb +970 -0
  46. data/lib/win32/Console/ANSI.rb +305 -0
  47. data/support/kvm.h +91 -0
  48. data/support/ruby-pcap-takuma-notes.txt +19 -0
  49. data/support/ruby-pcap-takuma-patch.txt +30 -0
  50. data/support/text/en.yaml +80 -0
  51. data/support/text/nl.yaml +7 -0
  52. data/support/useragents.txt +75 -0
  53. data/tests/01-util_test.rb +0 -0
  54. data/tests/02-stella-util_test.rb +42 -0
  55. data/tests/10-stella_test.rb +104 -0
  56. data/tests/11-stella-storable_test.rb +68 -0
  57. data/tests/60-stella-command_test.rb +248 -0
  58. data/tests/80-stella-cli_test.rb +45 -0
  59. data/tests/spec-helper.rb +31 -0
  60. metadata +165 -0
@@ -0,0 +1,15 @@
1
+
2
+
3
+ module MathUtil
4
+
5
+ # enforce_limit
6
+ #
7
+ # Enforce a minimum and maximum value
8
+ def self.enforce_limit(val,min,max)
9
+ val = min if val < min
10
+ val = max if val > max
11
+ val
12
+ end
13
+
14
+ end
15
+
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2005 Zed A. Shaw
2
+ # You can redistribute it and/or modify it under the same terms as Ruby.
3
+ #
4
+ # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
5
+ # for more information.
6
+
7
+ # A very simple little class for doing some basic fast statistics sampling.
8
+ # You feed it either samples of numeric data you want measured or you call
9
+ # Stats.tick to get it to add a time delta between the last time you called it.
10
+ # When you're done either call sum, sumsq, n, min, max, mean or sd to get
11
+ # the information. The other option is to just call dump and see everything.
12
+ #
13
+ # It does all of this very fast and doesn't take up any memory since the samples
14
+ # are not stored but instead all the values are calculated on the fly.
15
+
16
+ class Stats
17
+ attr_reader :sum, :sumsq, :n, :min, :max
18
+
19
+ def initialize(name=:unknown)
20
+ @name = name
21
+ reset
22
+ end
23
+
24
+ # Resets the internal counters so you can start sampling again.
25
+ def reset
26
+ @sum = 0.0
27
+ @sumsq = 0.0
28
+ @last_time = Time.new
29
+ @n = 0.0
30
+ @min = 0.0
31
+ @max = 0.0
32
+ end
33
+
34
+ # Adds a sampling to the calculations.
35
+ def sample(s)
36
+ @sum += s
37
+ @sumsq += s * s
38
+ if @n == 0
39
+ @min = @max = s
40
+ else
41
+ @min = s if @min > s
42
+ @max = s if @max < s
43
+ end
44
+ (@n+=1).to_f
45
+ end
46
+
47
+ # Dump this Stats object with an optional additional message.
48
+ def dump(msg = "", out=STDERR)
49
+ out.puts "#{msg}: #{self.to_s}"
50
+ end
51
+
52
+ # Returns a common display (used by dump)
53
+ def to_s
54
+ "[#{@name}]: SUM=%0.4f, SUMSQ=%0.4f, N=%0.4f, MEAN=%0.4f, SD=%0.4f, MIN=%0.4f, MAX=%0.4f" % [@sum, @sumsq, @n, mean, sd, @min, @max]
55
+ end
56
+
57
+
58
+ # Calculates and returns the mean for the data passed so far.
59
+ def mean
60
+ @sum / @n
61
+ end
62
+
63
+ # Calculates the standard deviation of the data so far.
64
+ def sd
65
+ # (sqrt( ((s).sumsq - ( (s).sum * (s).sum / (s).n)) / ((s).n-1) ))
66
+ begin
67
+ return Math.sqrt( (@sumsq - ( @sum * @sum / @n)) / (@n-1) ).to_f
68
+ rescue Errno::EDOM
69
+ return 0.0
70
+ end
71
+ end
72
+
73
+
74
+ # Adds a time delta between now and the last time you called this. This
75
+ # will give you the average time between two activities.
76
+ #
77
+ # An example is:
78
+ #
79
+ # t = Stats.new("do_stuff")
80
+ # 10000.times { do_stuff(); t.tick }
81
+ # t.dump("time")
82
+ #
83
+ def tick
84
+ now = Time.now
85
+ sample(now - @last_time)
86
+ @last_time = now
87
+ end
88
+ end
@@ -0,0 +1,267 @@
1
+ # A port of Text::Graph, which generates pretty ascii bar graphs from
2
+ # numeric datasets, like
3
+ #
4
+ # aaaa : (1)
5
+ # bb :..* (22)
6
+ # ccc :...* (43)
7
+ # dddddd :.....* (500)
8
+ # ee :......*(1000)
9
+ # f :.....* (300)
10
+ # ghi :...* (50)
11
+ #
12
+ # It accepts data in the following forms (see the 'extract' method):
13
+ #
14
+ # # { label => value, label => value, ... }
15
+ # # { :values => { label => value, ...} }
16
+ # # { :values => [values] }
17
+ # # {:values => { label => value, label => value }, :labels => [...]}
18
+ # # {:values => [values], :labels => [labels]}
19
+ # # [ [label, value], [label, value], ...]
20
+ # # [[values], [labels]]
21
+ #
22
+ # Numeric parameters:
23
+ # :minval
24
+ # :maxval
25
+ # :maxlen
26
+ #
27
+ # Boolean parameters:
28
+ # :log # logarithmic scale
29
+ # :right # label justification
30
+ #
31
+ # Display parameters:
32
+ # :marker
33
+ # :fill
34
+ # :separator
35
+ # :style # {:bar|:line} - sets default values for marker and fill
36
+ # :showval # numeric value after bar
37
+
38
+ # Text::Graph
39
+ # Port of Wade Johnson's Text::Graph for perl
40
+ # http://search.cpan.org/src/GWADEJ/Text-Graph-0.23/Graph.pm
41
+ #
42
+ # Author: Martin DeMello <martindeme...@gmail.com>
43
+
44
+ module Enumerable
45
+ def minmax
46
+ min = 1.0/0
47
+ max = -1.0/0
48
+ each {|i|
49
+ min = i if i < min
50
+ max = i if i > max
51
+ }
52
+ [min, max]
53
+ end
54
+
55
+ def map_with_index
56
+ a = []
57
+ each_with_index {|e, i| a << yield(e,i)}
58
+ a
59
+ end
60
+ end
61
+
62
+ class TextGraph
63
+ include Math
64
+
65
+ def initialize(data, params = {})
66
+ @data = extract(data)
67
+ @params = {:style => (params[:style] || :bar)}
68
+ apply_style(@params[:style])
69
+ @params.update(params)
70
+ @params[:separator] ||= " :"
71
+ end
72
+
73
+ def update_params(par)
74
+ apply_style(par[:style]) if par[:style]
75
+ @params.update(par)
76
+ end
77
+
78
+ def apply_style(style)
79
+ if style == :bar
80
+ @params[:marker] = "*"
81
+ @params[:fill] = "*"
82
+ elsif style == :line
83
+ @params[:marker] = '*'
84
+ @params[:fill] = ' '
85
+ else
86
+ raise "Invalid style #{style}"
87
+ end
88
+ end
89
+
90
+ def extract(data)
91
+ if data.is_a? Array
92
+ if data.length == 2 and data[0].is_a? Array and data[1].is_a? Array
93
+ # [[values], [labels]]
94
+ a = {}
95
+ a[:values] = data[0]
96
+ a[:labels] = data[1]
97
+ data = a
98
+ else
99
+ # [ [label, value], [label, value], ...]
100
+ a = {:values => [], :labels => []}
101
+ data.each {|i,j| a[:labels] << i; a[:values] << j}
102
+ end
103
+ end
104
+
105
+ if (data.length == 2) and data[:values] and data[:labels]
106
+ if data[:values].is_a? Array
107
+ # {:values => [values], :labels => [labels]}
108
+ # do nothing
109
+ elsif data[:values].is_a? Hash
110
+ # {:values => { label => value, label => value }, :labels => [...]}
111
+ a = data[:labels].map {|i| data[:values][i]}
112
+ data[:values] = a
113
+ else
114
+ raise "Invalid valueset"
115
+ end
116
+ elsif (data.length == 1) and data[:values]
117
+ if data[:values].is_a? Array
118
+ # { :values => [values] }
119
+ data[:labels] = data[:values].map {""}
120
+ elsif data[:values].is_a? Hash
121
+ # { :values => { label => value, ...} }
122
+ data[:labels] = data[:values].keys.sort_by {|i| i.to_s}
123
+ data[:values] = data[:labels].map {|i| data[:values][i]}
124
+ else
125
+ raise "Invalid valueset"
126
+ end
127
+ else
128
+ # { label => value, label => value, ... }
129
+ a = {}
130
+ a[:labels] = data.keys.sort_by {|i| i.to_s}
131
+ a[:values] = a[:labels].map {|i| data[i]}
132
+ data = a
133
+ end
134
+ data[:labels].map! {|i| i.to_s}
135
+ data
136
+ end
137
+
138
+ def make_within(val, min, max)
139
+ (val < min) ? min : (val > max ? max : val)
140
+ end
141
+
142
+ def makebar(val, m, f)
143
+ val = (val + 0.5).to_i
144
+ (val > 0) ? (f*(val - 1) + m) : ""
145
+ end
146
+
147
+ def fmt_labels (right, labels)
148
+ len = labels.map {|i| i.length}.max
149
+ just = right ? :rjust : :ljust
150
+ labels.map {|i| i.send(just, len)}
151
+ end
152
+
153
+ def make_labelled_lines(data)
154
+ labels = fmt_labels(@params[:right], data[:labels])
155
+ lines = histogram(data)
156
+ lines.zip(labels).map {|line, label| label + @params[:separator] + line}
157
+ end
158
+
159
+ def histogram(data)
160
+ values = data[:values].dup
161
+ minval, maxval, maxlen =
162
+ @params[:minval], @params[:maxval], @params[:maxlen]
163
+
164
+ if @params[:log]
165
+ values.map! {|i| log(i)}
166
+ minval = log(minval) rescue 1 if minval
167
+ maxval = log(maxval) rescue 1 if maxval
168
+ end
169
+
170
+ min, max = values.minmax
171
+ minval ||= min
172
+ maxval ||= max
173
+ maxl = maxval - minval + 1
174
+ maxlen ||= maxl
175
+ scale = maxlen*1.0/maxl
176
+ values = values.map {|i|
177
+ j = make_within(i, minval, maxval) - minval
178
+ makebar(j*scale, @params[:marker], @params[:fill])
179
+ }
180
+
181
+ if(@params[:showval])
182
+ values = values.map_with_index {|v, i|
183
+ v.ljust(maxlen) + "(#{data[:values][i]})"
184
+ }
185
+ end
186
+
187
+ values
188
+ end
189
+
190
+ def to_s
191
+ make_labelled_lines(@data).join("\n") + "\n"
192
+ end
193
+ end
194
+
195
+ if __FILE__ == $0
196
+
197
+ a = TextGraph.new({
198
+ :values => [100,142,43,54,111,62,52],
199
+ :labels => %w(aaaa bb ccc dddddd ee f ghi)
200
+ })
201
+
202
+ puts a
203
+
204
+ # aaaa :
205
+ # bb :*
206
+ # ccc :***
207
+ # dddddd :****
208
+ # ee :*********
209
+ # f :**
210
+ # ghi :****
211
+
212
+ puts "-------------------------------------------------------------"
213
+
214
+ a.update_params(:style => :line, :right => true, :showval => true)
215
+ puts a
216
+
217
+ # aaaa : (1)
218
+ # bb :* (2)
219
+ # ccc : * (4)
220
+ # dddddd : * (5)
221
+ # ee : * (10)
222
+ # f : * (3)
223
+ # ghi : * (5)
224
+
225
+ puts "-------------------------------------------------------------"
226
+
227
+ b = TextGraph.new({ :a=>1, :b=>5, :c=>20, :d=>10, :e=>17 }, {:maxlen => 10})
228
+ puts b
229
+
230
+ # a :
231
+ # b :**
232
+ # c :**********
233
+ # d :*****
234
+ # e :********
235
+
236
+ puts "-------------------------------------------------------------"
237
+
238
+ c = TextGraph.new({:values => { :a=>1, :b=>5, :c=>20, :d=>10, :e=>17 },
239
+ :labels => [:a, :c, :d]},
240
+ {:minval => 0, :maxval => 15, :showval => true})
241
+ puts c
242
+
243
+ # a :* (1)
244
+ # c :*************** (20)
245
+ # d :********** (10)
246
+
247
+ puts "-------------------------------------------------------------"
248
+
249
+ d = TextGraph.new([[10,22,43,500,1000,300,50], %w(aaaa bb ccc dddddd ee f ghi)],
250
+ { :style => :line,
251
+ :right => true, # right-justify labels
252
+ :fill => '.', # change fill-marker
253
+ :log => false, # logarithmic graph
254
+ :showval => true # show actual values
255
+ }
256
+ )
257
+ puts d
258
+
259
+ # aaaa : (1)
260
+ # bb :..* (22)
261
+ # ccc :...* (43)
262
+ # dddddd :.....* (500)
263
+ # ee :......*(1000)
264
+ # f :.....* (300)
265
+ # ghi :...* (50)
266
+
267
+ end
@@ -0,0 +1,58 @@
1
+
2
+ require 'benchmark'
3
+
4
+ class TimerUtil
5
+
6
+ attr_reader :tstart, :tend, :rstart, :rend
7
+ attr_reader :time
8
+
9
+ def initialize(label="default")
10
+ @tstart, @rstart = 0,0
11
+ @tend, @rend = 0,0
12
+ @label = label
13
+ @time = Benchmark::Tms.new
14
+ end
15
+
16
+ def start
17
+ @tstart, @rstart = Benchmark.times, Time.now
18
+ end
19
+
20
+ def stop
21
+ @tend, @rend = Benchmark.times, Time.now
22
+
23
+ @time = Benchmark::Tms.new(@tend.utime - @tstart.utime,
24
+ @tend.stime - @tstart.stime,
25
+ @tend.cutime - @tstart.cutime,
26
+ @tend.cstime - @tstart.cstime,
27
+ @rend.to_f - @rstart.to_f,
28
+ @label)
29
+ end
30
+
31
+ def utime
32
+ @time.utime
33
+ end
34
+ def stime
35
+ @time.stime
36
+ end
37
+ def cutime
38
+ @time.cutime
39
+ end
40
+ def cstime
41
+ @time.cstime
42
+ end
43
+ def total
44
+ @time.total
45
+ end
46
+ def real
47
+ @time.real
48
+ end
49
+ def format(formatstr=nil)
50
+ @time.format(formatstr)
51
+ end
52
+ def label
53
+ @time.label
54
+ end
55
+
56
+ end
57
+
58
+
@@ -0,0 +1,970 @@
1
+ # Win32::Console: an object implementing the Win32 API Console functions
2
+ # Copyright (C) 2003 Gonzalo Garramuno (ggarramuno@aol.com)
3
+ #
4
+ # Original Win32API_Console was:
5
+ # Copyright (C) 2001 Michael L. Semon (mlsemon@sega.net)
6
+
7
+ begin
8
+ # If Console.so is available, use that. Otherwise, we define
9
+ # equivalent functions in ruby (a tad slower)
10
+ # That dll should define everything in an identical interface
11
+ # to all the ruby code that the rescue below defines.
12
+ require "Console.so"
13
+ STDERR.print "Using faster, DLL Console.so\n" if $DEBUG
14
+
15
+ rescue Exception
16
+
17
+ STDERR.print "Using slower, non-DLL Console.rb\n" if $DEBUG
18
+
19
+ module Win32
20
+ class Console
21
+ end
22
+ end
23
+
24
+ # The WINDOWS constants
25
+ module Win32::Console::Constants
26
+ STD_INPUT_HANDLE = 0xFFFFFFF6
27
+ STD_OUTPUT_HANDLE = 0xFFFFFFF5
28
+ STD_ERROR_HANDLE = 0xFFFFFFF4
29
+ INVALID_HANDLE_VALUE = 0xFFFFFFFF
30
+ GENERIC_READ = 0x80000000
31
+ GENERIC_WRITE = 0x40000000
32
+ FILE_SHARE_READ = 0x00000001
33
+ FILE_SHARE_WRITE = 0x00000002
34
+ CONSOLE_TEXTMODE_BUFFER = 0x00000001
35
+
36
+ FOREGROUND_BLUE = 0x0001
37
+ FOREGROUND_GREEN = 0x0002
38
+ FOREGROUND_RED = 0x0004
39
+ FOREGROUND_INTENSITY = 0x0008
40
+ BACKGROUND_BLUE = 0x0010
41
+ BACKGROUND_GREEN = 0x0020
42
+ BACKGROUND_RED = 0x0040
43
+ BACKGROUND_INTENSITY = 0x0080
44
+
45
+ ENABLE_PROCESSED_INPUT = 0x0001
46
+ ENABLE_LINE_INPUT = 0x0002
47
+ ENABLE_ECHO_INPUT = 0x0004
48
+ ENABLE_WINDOW_INPUT = 0x0008
49
+ ENABLE_MOUSE_INPUT = 0x0010
50
+ ENABLE_PROCESSED_OUTPUT = 0x0001
51
+ ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
52
+
53
+ KEY_EVENT = 0x0001
54
+ MOUSE_EVENT = 0x0002
55
+ WINDOW_BUFFER_SIZE_EVENT = 0x0004
56
+ MENU_EVENT = 0x0008
57
+ FOCUS_EVENT = 0x0010
58
+
59
+ CAPSLOCK_ON = 0x0080
60
+ ENHANCED_KEY = 0x0100
61
+ NUMLOCK_ON = 0x0020
62
+ SHIFT_PRESSED = 0x0010
63
+ LEFT_CTRL_PRESSED = 0x0008
64
+ RIGHT_CTRL_PRESSED = 0x0004
65
+ LEFT_ALT_PRESSED = 0x0002
66
+ RIGHT_ALT_PRESSED = 0x0001
67
+ SCROLLLOCK_ON = 0x0040
68
+
69
+ MOUSE_WHEELED = 0x0004
70
+ DOUBLE_CLICK = 0x0002
71
+ MOUSE_MOVED = 0x0001
72
+
73
+ FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001
74
+ FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004
75
+ FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008
76
+ FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010
77
+ RIGHTMOST_BUTTON_PRESSED = 0x0002
78
+
79
+ CTRL_C_EVENT = 0x0000
80
+ CTRL_BREAK_EVENT = 0x0001
81
+ CTRL_CLOSE_EVENT = 0x0002
82
+ CTRL_LOGOFF_EVENT = 0x0005
83
+ CTRL_SHUTDOWN_EVENT = 0x0006
84
+ end
85
+
86
+ # The actual api to access windows functions
87
+ class Win32::Console::API
88
+ require 'Win32API'
89
+
90
+ private
91
+ # This is a class-wide cache that will hold Win32API objects. As each
92
+ # Win32API object is about 920 bytes, I didn't want to initialize all of
93
+ # them at one time. That would waste about 42 kB for this object because
94
+ # it has 47 functions. However, to not have a cache at all would reduce
95
+ # the speed of this object by 164%.
96
+ @@m_AllocConsole = nil
97
+ @@m_CreateConsoleScreenBuffer = nil
98
+ @@m_FillConsoleOutputAttribute = nil
99
+ @@m_FillConsoleOutputCharacter = nil
100
+ @@m_FlushConsoleInputBuffer = nil
101
+ @@m_FreeConsole = nil
102
+ @@m_GenerateConsoleCtrlEvent = nil
103
+ @@m_GetConsoleCP = nil
104
+ @@m_GetConsoleCursorInfo = nil
105
+ @@m_GetConsoleMode = nil
106
+ @@m_GetConsoleOutputCP = nil
107
+ @@m_GetConsoleScreenBufferInfo = nil
108
+ @@m_GetConsoleTitle = nil
109
+ @@m_GetConsoleWindow = nil
110
+ @@m_GetLargestConsoleWindowSize = nil
111
+ @@m_GetNumberOfConsoleInputEvents = nil
112
+ @@m_GetNumberOfConsoleMouseButtons = nil
113
+ @@m_GetStdHandle = nil
114
+ @@m_PeekConsoleInput = nil
115
+ @@m_ReadConsole = nil
116
+ @@m_ReadConsoleInput = nil
117
+ @@m_ReadConsoleOutput = nil
118
+ @@m_ReadConsoleOutputAttribute = nil
119
+ @@m_ReadConsoleOutputCharacter = nil
120
+ @@m_ScrollConsoleScreenBuffer = nil
121
+ @@m_SetConsoleActiveScreenBuffer = nil
122
+ @@m_SetConsoleCP = nil
123
+ @@m_SetConsoleCursorInfo = nil
124
+ @@m_SetConsoleCursorPosition = nil
125
+ @@m_SetConsoleMode = nil
126
+ @@m_SetConsoleOutputCP = nil
127
+ @@m_SetConsoleScreenBufferSize = nil
128
+ @@m_SetConsoleTextAttribute = nil
129
+ @@m_SetConsoleTitle = nil
130
+ @@m_SetConsoleWindowInfo = nil
131
+ @@m_SetStdHandle = nil
132
+ @@m_WriteConsole = nil
133
+ @@m_WriteConsoleInput = nil
134
+ @@m_WriteConsoleOutput = nil
135
+ @@m_WriteConsoleOutputAttribute = nil
136
+ @@m_WriteConsoleOutputCharacter = nil
137
+
138
+ public
139
+
140
+ class << self
141
+
142
+
143
+ def constant(t)
144
+ begin
145
+ eval "return Win32::Console::Constants::#{t}"
146
+ rescue
147
+ return nil
148
+ end
149
+ end
150
+
151
+
152
+ def AllocConsole()
153
+ if @@m_AllocConsole == nil
154
+ @@m_AllocConsole = Win32API.new( "kernel32", "AllocConsole",
155
+ [], 'l' )
156
+ end
157
+ @@m_AllocConsole.call()
158
+ end
159
+
160
+ def CreateConsoleScreenBuffer( dwDesiredAccess, dwShareMode, dwFlags )
161
+ if @@m_CreateConsoleScreenBuffer == nil
162
+ @@m_CreateConsoleScreenBuffer = Win32API.new( "kernel32", "CreateConsoleScreenBuffer", ['l', 'l', 'p', 'l', 'p'], 'l' )
163
+ end
164
+ @@m_CreateConsoleScreenBuffer.call( dwDesiredAccess, dwShareMode,
165
+ nil, dwFlags, nil )
166
+ end
167
+
168
+
169
+
170
+ def FillConsoleOutputAttribute( hConsoleOutput, wAttribute, nLength,
171
+ col, row )
172
+ if @@m_FillConsoleOutputAttribute == nil
173
+ @@m_FillConsoleOutputAttribute = Win32API.new( "kernel32", "FillConsoleOutputAttribute", ['l', 'i', 'l', 'l', 'p'], 'l' )
174
+ end
175
+ dwWriteCoord = (row << 16) + col
176
+ lpNumberOfAttrsWritten = ' ' * 4
177
+ @@m_FillConsoleOutputAttribute.call( hConsoleOutput, wAttribute,
178
+ nLength, dwWriteCoord,
179
+ lpNumberOfAttrsWritten )
180
+ return lpNumberOfAttrsWritten.unpack('L')
181
+ end
182
+
183
+
184
+
185
+ def FillConsoleOutputCharacter( hConsoleOutput, cCharacter, nLength,
186
+ col, row )
187
+ if @@m_FillConsoleOutputCharacter == nil
188
+ @@m_FillConsoleOutputCharacter = Win32API.new( "kernel32", "FillConsoleOutputCharacter", ['l', 'i', 'l', 'l', 'p'], 'l' )
189
+ end
190
+ dwWriteCoord = (row << 16) + col
191
+ lpNumberOfAttrsWritten = ' ' * 4
192
+ @@m_FillConsoleOutputCharacter.call( hConsoleOutput, cCharacter,
193
+ nLength, dwWriteCoord,
194
+ lpNumberOfAttrsWritten )
195
+ return lpNumberOfAttrsWritten.unpack('L')
196
+ end
197
+
198
+
199
+ def FlushConsoleInputBuffer( hConsoleInput )
200
+ if @@m_FlushConsoleInputBuffer == nil
201
+ @@m_FlushConsoleInputBuffer = Win32API.new( "kernel32",
202
+ "FillConsoleInputBuffer",
203
+ ['l'], 'l' )
204
+ end
205
+ @@m_FlushConsoleInputBuffer.call( hConsoleInput )
206
+ end
207
+
208
+
209
+ def FreeConsole()
210
+ if @@m_FreeConsole == nil
211
+ @@m_FreeConsole = Win32API.new( "kernel32", "FreeConsole", [], 'l' )
212
+ end
213
+ @@m_FreeConsole.call()
214
+ end
215
+
216
+
217
+ def GenerateConsoleCtrlEvent( dwCtrlEvent, dwProcessGroupId )
218
+ if @@m_GenerateConsoleCtrlEvent == nil
219
+ @@m_GenerateConsoleCtrlEvent = Win32API.new( "kernel32", "GenerateConsoleCtrlEvent", ['l', 'l'], 'l' )
220
+ end
221
+ @@m_GenerateConsoleCtrlEvent.call( dwCtrlEvent, dwProcessGroupId )
222
+ end
223
+
224
+ def GetConsoleCP()
225
+ if @@m_GetConsoleCP == nil
226
+ @@m_GetConsoleCP = Win32API.new( "kernel32", "GetConsoleCP",
227
+ [], 'l' )
228
+ end
229
+ @@m_GetConsoleCP.call()
230
+ end
231
+
232
+ def GetConsoleCursorInfo( hConsoleOutput )
233
+ if @@m_GetConsoleCursorInfo == nil
234
+ @@m_GetConsoleCursorInfo = Win32API.new( "kernel32",
235
+ "GetConsoleCursorInfo",
236
+ ['l', 'p'], 'l' )
237
+ end
238
+ lpConsoleCursorInfo = ' ' * 8
239
+ @@m_GetConsoleCursorInfo.call( hConsoleOutput, lpConsoleCursorInfo )
240
+ return lpConsoleCursorInfo.unpack('LL')
241
+ end
242
+
243
+ def GetConsoleMode( hConsoleHandle )
244
+ if @@m_GetConsoleMode == nil
245
+ @@m_GetConsoleMode = Win32API.new( "kernel32", "GetConsoleMode",
246
+ ['l', 'p'], 'l' )
247
+ end
248
+ lpMode = ' ' * 4
249
+ @@m_GetConsoleMode.call( hConsoleHandle, lpMode )
250
+ return lpMode.unpack('L')
251
+ end
252
+
253
+ def GetConsoleOutputCP()
254
+ if @@m_GetConsoleOutputCP == nil
255
+ @@m_GetConsoleOutputCP = Win32API.new( "kernel32",
256
+ "GetConsoleOutputCP", [], 'l' )
257
+ end
258
+ @@m_GetConsoleOutputCP.call()
259
+ end
260
+
261
+ def GetConsoleScreenBufferInfo( hConsoleOutput )
262
+ if @@m_GetConsoleScreenBufferInfo == nil
263
+ @@m_GetConsoleScreenBufferInfo = Win32API.new( "kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'l' )
264
+ end
265
+ lpBuffer = ' ' * 22
266
+ @@m_GetConsoleScreenBufferInfo.call( hConsoleOutput, lpBuffer )
267
+ return lpBuffer.unpack('SSSSSssssSS')
268
+ end
269
+
270
+ def GetConsoleTitle()
271
+ if @@m_GetConsoleTitle == nil
272
+ @@m_GetConsoleTitle = Win32API.new( "kernel32", "GetConsoleTitle",
273
+ ['p', 'l'], 'l' )
274
+ end
275
+ nSize = 120
276
+ lpConsoleTitle = ' ' * nSize
277
+ @@m_GetConsoleTitle.call( lpConsoleTitle, nSize )
278
+ return lpConsoleTitle.strip
279
+ end
280
+
281
+ def GetConsoleWindow()
282
+ if @@m_GetConsoleWindow == nil
283
+ @@m_GetConsoleWindow = Win32API.new( "kernel32", "GetConsoleWindow",
284
+ [], 'l' )
285
+ end
286
+ @@m_GetConsoleWindow.call()
287
+ end
288
+
289
+ def GetLargestConsoleWindowSize( hConsoleOutput )
290
+ if @@m_GetLargestConsoleWindowSize == nil
291
+ @@m_GetLargestConsoleWindowSize = Win32API.new( "kernel32", "GetLargestConsoleWindowSize", ['l'], 'l' )
292
+ end
293
+ coord = @@m_GetLargestConsoleWindowSize.call( hConsoleOutput )
294
+ x = coord >> 16
295
+ y = coord & 0x0000ffff
296
+ return [x,y]
297
+ end
298
+
299
+ def GetNumberOfConsoleInputEvents( hConsoleInput )
300
+ if @@m_GetNumberOfConsoleInputEvents == nil
301
+ @@m_GetNumberOfConsoleInputEvents = Win32API.new( "kernel32", "GetNumberOfConsoleInputEvents", ['l', 'p'], 'l' )
302
+ end
303
+ lpcNumberOfEvents = 0
304
+ @@m_GetNumberOfConsoleInputEvents.call( hConsoleInput,
305
+ lpcNumberOfEvents )
306
+ return lpcNumberOfEvents
307
+ end
308
+
309
+ def GetNumberOfConsoleMouseButtons( )
310
+ if @@m_GetNumberOfConsoleMouseButtons == nil
311
+ @@m_GetNumberOfConsoleMouseButtons = Win32API.new( "kernel32", "GetNumberOfConsoleMouseButtons", ['p'], 'l' )
312
+ end
313
+ lpNumberOfMouseButtons = 0
314
+ @@m_GetNumberOfConsoleMouseButtons.call( lpNumberOfMouseButtons )
315
+ return lpNumberOfMouseButtons
316
+ end
317
+
318
+ def GetStdHandle( nStdHandle )
319
+ if @@m_GetStdHandle == nil
320
+ @@m_GetStdHandle = Win32API.new( "kernel32", "GetStdHandle",
321
+ ['l'], 'l' )
322
+ end
323
+ @@m_GetStdHandle.call( nStdHandle )
324
+ end
325
+
326
+ # <<HandlerRoutine>> : This is not an actual API function, just a concept description in the SDK.
327
+
328
+ def PeekConsoleInput( hConsoleInput )
329
+ if @@m_PeekConsoleInput == nil
330
+ @@m_PeekConsoleInput = Win32API.new( "kernel32", "PeekConsoleInput",
331
+ ['l', 'p', 'l', 'p'], 'l' )
332
+ end
333
+ lpNumberOfEventsRead = ' ' * 4
334
+ lpBuffer = ' ' * 20
335
+ nLength = 20
336
+ @@m_PeekConsoleInput.call( hConsoleInput, lpBuffer, nLength,
337
+ lpNumberOfEventsRead )
338
+ type = lpBuffer.unpack('s')[0]
339
+
340
+ case type
341
+ when KEY_EVENT
342
+ return lpBuffer.unpack('sSSSSCS')
343
+ when MOUSE_EVENT
344
+ return lpBuffer.unpack('sSSSS')
345
+ when WINDOW_BUFFER_SIZE_EVENT
346
+ return lpBuffer.unpack('sS')
347
+ when MENU_EVENT
348
+ return lpBuffer.unpack('sS')
349
+ when FOCUS_EVENT
350
+ return lpBuffer.unpack('sS')
351
+ else
352
+ return []
353
+ end
354
+ end
355
+
356
+ def ReadConsole( hConsoleInput, lpBuffer, nNumberOfCharsToRead )
357
+ if @@m_ReadConsole == nil
358
+ @@m_ReadConsole = Win32API.new( "kernel32", "ReadConsole",
359
+ ['l', 'p', 'l', 'p', 'p'], 'l' )
360
+ end
361
+ lpBuffer = ' ' * nNumberOfCharsToRead unless lpBuffer
362
+ lpNumberOfCharsRead = ' ' * 4
363
+ lpReserved = ' ' * 4
364
+ @@m_ReadConsole.call( hConsoleInput, lpBuffer, nNumberOfCharsToRead,
365
+ lpNumberOfCharsRead, lpReserved )
366
+ return lpNumberOfCharsRead.unpack('L')
367
+ end
368
+
369
+ def ReadConsoleInput( hConsoleInput )
370
+ if @@m_ReadConsoleInput == nil
371
+ @@m_ReadConsoleInput = Win32API.new( "kernel32", "ReadConsoleInput",
372
+ ['l', 'p', 'l', 'p'], 'l' )
373
+ end
374
+ lpNumberOfEventsRead = ' ' * 4
375
+ lpBuffer = ' ' * 20
376
+ nLength = 20
377
+ @@m_ReadConsoleInput.call( hConsoleInput, lpBuffer, nLength,
378
+ lpNumberOfEventsRead )
379
+ type = lpBuffer.unpack('s')[0]
380
+
381
+ case type
382
+ when KEY_EVENT
383
+ return lpBuffer.unpack('sSSSSCS')
384
+ when MOUSE_EVENT
385
+ return lpBuffer.unpack('sSSSS')
386
+ when WINDOW_BUFFER_SIZE_EVENT
387
+ return lpBuffer.unpack('sS')
388
+ when MENU_EVENT
389
+ return lpBuffer.unpack('sS')
390
+ when FOCUS_EVENT
391
+ return lpBuffer.unpack('sS')
392
+ else
393
+ return []
394
+ end
395
+ end
396
+
397
+ def ReadConsoleOutput( hConsoleOutput, lpBuffer, cols, rows,
398
+ bufx, bufy, left, top, right, bottom )
399
+ if @@m_ReadConsoleOutput == nil
400
+ @@m_ReadConsoleOutput = Win32API.new( "kernel32",
401
+ "ReadConsoleOutput",
402
+ ['l', 'p', 'l', 'l', 'p'], 'l' )
403
+ end
404
+ dwBufferSize = cols * rows * 4
405
+ lpBuffer = ' ' * dwBufferSize
406
+ dwBufferCoord = (bufy << 16) + bufx
407
+ lpReadRegion = [ left, top, right, bottom ].pack('ssss')
408
+ @@m_ReadConsoleOutput.call( hConsoleOutput, lpBuffer, dwBufferSize,
409
+ dwBufferCoord, lpReadRegion )
410
+ end
411
+
412
+ def ReadConsoleOutputAttribute( hConsoleOutput, nLength, col, row )
413
+ if @@m_ReadConsoleOutputAttribute == nil
414
+ @@m_ReadConsoleOutputAttribute = Win32API.new( "kernel32", "ReadConsoleOutputAttribute", ['l', 'p', 'l', 'l', 'p'], 'l' )
415
+ end
416
+ lpAttribute = ' ' * nLength
417
+ dwReadCoord = (row << 16) + col
418
+ lpNumberOfAttrsRead = ' ' * 4
419
+ @@m_ReadConsoleOutputAttribute.call( hConsoleOutput, lpAttribute,
420
+ nLength, dwReadCoord,
421
+ lpNumberOfAttrsRead )
422
+ return lpAttribute
423
+ end
424
+
425
+ def ReadConsoleOutputCharacter( hConsoleOutput, lpCharacter, nLength,
426
+ col, row )
427
+ if @@m_ReadConsoleOutputCharacter == nil
428
+ @@m_ReadConsoleOutputCharacter = Win32API.new( "kernel32", "ReadConsoleOutputCharacter", ['l', 'p', 'l', 'l', 'p'], 'l' )
429
+ end
430
+ dwReadCoord = (row << 16) + col
431
+ lpNumberOfCharsRead = ' ' * 4
432
+ @@m_ReadConsoleOutputCharacter.call( hConsoleOutput, lpCharacter,
433
+ nLength, dwReadCoord,
434
+ lpNumberOfCharsRead )
435
+ return lpNumberOfCharsRead.unpack('L')
436
+ end
437
+
438
+ def ScrollConsoleScreenBuffer( hConsoleOutput,
439
+ left1, top1, right1, bottom1,
440
+ col, row, char, attr,
441
+ left2, top2, right2, bottom2 )
442
+ if @@m_ScrollConsoleScreenBuffer == nil
443
+ @@m_ScrollConsoleScreenBuffer = Win32API.new( "kernel32", "ScrollConsoleScreenBuffer", ['l', 'p', 'p', 'l', 'p'], 'l' )
444
+ end
445
+ lpScrollRectangle = [left1, top1, right1, bottom1].pack('ssss')
446
+ lpClipRectangle = [left2, top2, right2, bottom2].pack('ssss')
447
+ dwDestinationOrigin = (row << 16) + col
448
+ lpFill = [char, attr].pack('ss')
449
+ @@m_ScrollConsoleScreenBuffer.call( hConsoleOutput, lpScrollRectangle,
450
+ lpClipRectangle,
451
+ dwDestinationOrigin, lpFill )
452
+ end
453
+
454
+ def SetConsoleActiveScreenBuffer( hConsoleOutput )
455
+ if @@m_SetConsoleActiveScreenBuffer == nil
456
+ @@m_SetConsoleActiveScreenBuffer = Win32API.new( "kernel32", "SetConsoleActiveScreenBuffer", ['l'], 'l' )
457
+ end
458
+ @@m_SetConsoleActiveScreenBuffer.call( hConsoleOutput )
459
+ end
460
+
461
+ # <<SetConsoleCtrlHandler>>: Will probably not be implemented.
462
+
463
+ def SetConsoleCP( wCodePageID )
464
+ if @@m_SetConsoleCP == nil
465
+ @@m_SetConsoleCP = Win32API.new( "kernel32", "SetConsoleCP",
466
+ ['l'], 'l' )
467
+ end
468
+ @@m_SetConsoleCP.call( wCodePageID )
469
+ end
470
+
471
+ def SetConsoleCursorInfo( hConsoleOutput, col, row )
472
+ if @@m_SetConsoleCursorInfo == nil
473
+ @@m_SetConsoleCursorInfo = Win32API.new( "kernel32",
474
+ "SetConsoleCursorInfo",
475
+ ['l', 'p'], 'l' )
476
+ end
477
+ lpConsoleCursorInfo = [size,visi].pack('LL')
478
+ @@m_SetConsoleCursorInfo.call( hConsoleOutput, lpConsoleCursorInfo )
479
+ end
480
+
481
+ def SetConsoleCursorPosition( hConsoleOutput, col, row )
482
+ if @@m_SetConsoleCursorPosition == nil
483
+ @@m_SetConsoleCursorPosition = Win32API.new( "kernel32", "SetConsoleCursorPosition", ['l', 'p'], 'l' )
484
+ end
485
+ dwCursorPosition = (row << 16) + col
486
+ @@m_SetConsoleCursorPosition.call( hConsoleOutput, dwCursorPosition )
487
+ end
488
+
489
+ def SetConsoleMode( hConsoleHandle, lpMode )
490
+ if @@m_SetConsoleMode == nil
491
+ @@m_SetConsoleMode = Win32API.new( "kernel32", "SetConsoleMode",
492
+ ['l', 'p'], 'l' )
493
+ end
494
+ @@m_SetConsoleMode.call( hConsoleHandle, lpMode )
495
+ end
496
+
497
+ def SetConsoleOutputCP( wCodePageID )
498
+ if @@m_SetConsoleOutputCP == nil
499
+ @@m_SetConsoleOutputCP = Win32API.new( "kernel32",
500
+ "GetConsoleOutputCP",
501
+ ['l'], 'l' )
502
+ end
503
+ @@m_SetConsoleOutputCP.call( wCodePageID )
504
+ end
505
+
506
+ def SetConsoleScreenBufferSize( hConsoleOutput, col, row )
507
+ if @@m_SetConsoleScreenBufferSize == nil
508
+ @@m_SetConsoleScreenBufferSize = Win32API.new( "kernel32", "SetConsoleScreenBufferSize", ['l', 'l'], 'l' )
509
+ end
510
+ dwSize = (row << 16) + col
511
+ @@m_SetConsoleScreenBufferSize.call( hConsoleOutput, dwSize )
512
+ end
513
+
514
+ def SetConsoleTextAttribute( hConsoleOutput, wAttributes )
515
+ if @@m_SetConsoleTextAttribute == nil
516
+ @@m_SetConsoleTextAttribute = Win32API.new( "kernel32", "SetConsoleTextAttribute", ['l', 'i'], 'l' )
517
+ end
518
+ @@m_SetConsoleTextAttribute.call( hConsoleOutput, wAttributes )
519
+ end
520
+
521
+ def SetConsoleTitle( lpConsoleTitle )
522
+ if @@m_SetConsoleTitle == nil
523
+ @@m_SetConsoleTitle = Win32API.new( "kernel32", "SetConsoleTitle",
524
+ ['p'], 'l' )
525
+ end
526
+ @@m_SetConsoleTitle.call( lpConsoleTitle )
527
+ end
528
+
529
+ def SetConsoleWindowInfo( hConsoleOutput, bAbsolute,
530
+ left, top, right, bottom )
531
+ if @@m_SetConsoleWindowInfo == nil
532
+ @@m_SetConsoleWindowInfo = Win32API.new( "kernel32",
533
+ "SetConsoleWindowInfo",
534
+ ['l', 'l', 'p'], 'l' )
535
+ end
536
+ lpConsoleWindow = [ left, top, right, bottom ].pack('ssss')
537
+ @@m_SetConsoleWindowInfo.call( hConsoleOutput, bAbsolute,
538
+ lpConsoleWindow )
539
+ end
540
+
541
+ def SetStdHandle( nStdHandle, hHandle )
542
+ if @@m_SetStdHandle == nil
543
+ @@m_SetStdHandle = Win32API.new( "kernel32", "SetStdHandle",
544
+ ['l', 'l'], 'l' )
545
+ end
546
+ @@m_SetStdHandle.call( nStdHandle, hHandle )
547
+ end
548
+
549
+ def WriteConsole( hConsoleOutput, lpBuffer )
550
+ if @@m_WriteConsole == nil
551
+ @@m_WriteConsole = Win32API.new( "kernel32", "WriteConsole",
552
+ ['l', 'p', 'l', 'p', 'p'], 'l' )
553
+ end
554
+ nNumberOfCharsToWrite = lpBuffer.length()
555
+ lpNumberOfCharsWritten = ' ' * 4
556
+ lpReserved = ' ' * 4
557
+ @@m_WriteConsole.call( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
558
+ lpNumberOfCharsWritten, lpReserved )
559
+ return lpNumberOfCharsWritten
560
+ end
561
+
562
+ def WriteConsoleInput( hConsoleInput, lpBuffer )
563
+ if @@m_WriteConsoleInput == nil
564
+ @@m_WriteConsoleInput = Win32API.new( "kernel32", "WriteConsoleInput", ['l', 'p', 'l', 'p'], 'l' )
565
+ end
566
+ @@m_WriteConsoleInput.call( hConsoleInput, lpBuffer, nLength,
567
+ lpNumberOfEventsWritten )
568
+ end
569
+
570
+ # @@ Todo: Test this
571
+ def WriteConsoleOutput( hConsoleOutput, buffer, cols, rows,
572
+ bufx, bufy, left, top, right, bottom )
573
+ if @@m_WriteConsoleOutput == nil
574
+ @@m_WriteConsoleOutput = Win32API.new( "kernel32", "WriteConsoleOutput", ['l', 'p', 'l', 'l', 'p'], 'l' )
575
+ end
576
+ lpBuffer = buffer.flatten.pack('ss' * buffer.length() * 2)
577
+ dwBufferSize = (buffer.length() << 16) + 2
578
+ dwBufferCoord = (row << 16) + col
579
+ lpWriteRegion = [ left, top, right, bottom ].pack('ssss')
580
+ @@m_WriteConsoleOutput.call( hConsoleOutput, lpBuffer, dwBufferSize,
581
+ dwBufferCoord, lpWriteRegion )
582
+ end
583
+
584
+ def WriteConsoleOutputAttribute( hConsoleOutput, lpAttribute, col, row )
585
+ if @@m_WriteConsoleOutputAttribute == nil
586
+ @@m_WriteConsoleOutputAttribute = Win32API.new( "kernel32", "WriteConsoleOutputAttribute", ['l', 'p', 'l', 'l', 'p'], 'l' )
587
+ end
588
+ nLength = lpAttribute.length()
589
+ dwWriteCoord = (row << 16) + col
590
+ lpNumberOfAttrsWritten = ' ' * 4
591
+ @@m_WriteConsoleOutputAttribute.call( hConsoleOutput, lpAttribute,
592
+ nLength, dwWriteCoord,
593
+ lpNumberOfAttrsWritten )
594
+ return lpNumberOfAttrsWritten.unpack('L')
595
+ end
596
+
597
+ def WriteConsoleOutputCharacter( hConsoleOutput, lpCharacter, col, row )
598
+ if @@m_WriteConsoleOutputCharacter == nil
599
+ @@m_WriteConsoleOutputCharacter = Win32API.new( "kernel32", "WriteConsoleOutputCharacter", ['l', 'p', 'l', 'l', 'p'], 'l' )
600
+ end
601
+ nLength = lpCharacter.length()
602
+ dwWriteCoord = (row << 16) + col
603
+ lpNumberOfCharsWritten = ' ' * 4
604
+ @@m_WriteConsoleOutputCharacter.call( hConsoleOutput, lpCharacter,
605
+ nLength, dwWriteCoord,
606
+ lpNumberOfCharsWritten )
607
+ return lpNumberOfCharsWritten.unpack('L')
608
+ end
609
+
610
+ end
611
+ end
612
+
613
+ end # rescue
614
+
615
+
616
+
617
+ module Win32
618
+ class Console
619
+
620
+ VERSION = '1.0'
621
+
622
+ include Win32::Console::Constants
623
+
624
+ def initialize( t = nil )
625
+ if t and ( t == STD_INPUT_HANDLE or t == STD_OUTPUT_HANDLE or
626
+ t == STD_ERROR_HANDLE )
627
+ @handle = API.GetStdHandle( t )
628
+ else
629
+ param1 = GENERIC_READ | GENERIC_WRITE
630
+ param2 = FILE_SHARE_READ | FILE_SHARE_WRITE
631
+ @handle = API.CreateConsoleScreenBuffer( param1, param2,
632
+ CONSOLE_TEXTMODE_BUFFER )
633
+ end
634
+ end
635
+
636
+
637
+ def Display
638
+ return API.SetConsoleActiveScreenBuffer(@handle)
639
+ end
640
+
641
+ def Select(type)
642
+ return API.SetStdHandle(type,@handle)
643
+ end
644
+
645
+ def Title(title = nil)
646
+ if title
647
+ return API.SetConsoleTitle(title)
648
+ else
649
+ return API.GetConsoleTitle()
650
+ end
651
+ end
652
+
653
+ def WriteChar(s, col, row)
654
+ API.WriteConsoleOutputCharacter( @handle, s, col, row )
655
+ end
656
+
657
+ def ReadChar(size, col, row)
658
+ buffer = ' ' * size
659
+ if API.ReadConsoleOutputCharacter( @handle, buffer, size, col, row )
660
+ return buffer
661
+ else
662
+ return nil
663
+ end
664
+ end
665
+
666
+ def WriteAttr(attr, col, row)
667
+ API.WriteConsoleOutputAttribute( @handle, attr, col, row )
668
+ end
669
+
670
+ def ReadAttr(size, col, row)
671
+ x = API.ReadConsoleOutputAttribute( @handle, size, col, row )
672
+ return x.unpack('c'*size)
673
+ end
674
+
675
+
676
+ def Cursor(*t)
677
+ col, row, size, visi = t
678
+ if col
679
+ row = -1 if !row
680
+ if col < 0 or row < 0
681
+ curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
682
+ col = curr_col if col < 0
683
+ row = curr_row if row < 0
684
+ end
685
+ API.SetConsoleCursorPosition( @handle, col, row )
686
+ if size and visi
687
+ curr_size, curr_visi = API.GetConsoleCursorInfo( @handle )
688
+ size = curr_size if size < 0
689
+ visi = curr_visi if visi < 0
690
+ size = 1 if size < 1
691
+ size = 99 if size > 99
692
+ API.SetConsoleCursorInfo( @handle, size, visi )
693
+ end
694
+ else
695
+ d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
696
+ curr_size, curr_visi = API.GetConsoleCursorInfo( @handle )
697
+ return [ curr_col, curr_row, curr_size, curr_visi ]
698
+ end
699
+ end
700
+
701
+ def Write(s)
702
+ API.WriteConsole( @handle, s )
703
+ end
704
+
705
+ def ReadRect( left, top, right, bottom )
706
+ col = right - left + 1
707
+ row = bottom - top + 1
708
+ size = col * row
709
+ buffer = ' ' * size * 4
710
+ if API.ReadConsoleOutput( @handle, buffer, col, row, 0, 0,
711
+ left, top, right, bottom )
712
+ #return buffer.unpack('US'*size) # for unicode
713
+ return buffer.unpack('axS'*size) # for ascii
714
+ else
715
+ return nil
716
+ end
717
+ end
718
+
719
+ def WriteRect( buffer, left, top, right, bottom )
720
+ col = right - left + 1
721
+ row = bottom - top + 1
722
+ API.WriteConsoleOutput( @handle, buffer, col, row, 0, 0,
723
+ left, top, right, bottom )
724
+ end
725
+
726
+
727
+
728
+ def Scroll( left1, top1, right1, bottom1,
729
+ col, row, char, attr,
730
+ left2, top2, right2, bottom2 )
731
+ API.ScrollConsoleScreenBuffer(@handle, left1, top1, right1, bottom1,
732
+ col, row, char, attr,
733
+ left2, top2, right2, bottom2)
734
+ end
735
+
736
+
737
+ def MaxWindow(flag = nil)
738
+ if !flag
739
+ info = API.GetConsoleScreenBufferInfo(@handle)
740
+ return info[9], info[10]
741
+ else
742
+ return API.GetLargestConsoleWindowSize(@handle)
743
+ end
744
+ end
745
+
746
+
747
+ def Info()
748
+ return API.GetConsoleScreenBufferInfo( @handle )
749
+ end
750
+
751
+
752
+ def GetEvents()
753
+ return API.GetNumberOfConsoleInputEvents(@handle)
754
+ end
755
+
756
+
757
+ def Flush()
758
+ return API.FlushConsoleInputBuffer(@handle)
759
+ end
760
+
761
+ def InputChar(number = nil)
762
+ number = 1 unless number
763
+ buffer = ' ' * number
764
+ if API.ReadConsole(@handle, buffer, number) == number
765
+ return buffer
766
+ else
767
+ return nil
768
+ end
769
+ end
770
+
771
+
772
+ def Input()
773
+ API.ReadConsoleInput(@handle)
774
+ end
775
+
776
+
777
+ def PeekInput()
778
+ API.PeekConsoleInput(@handle)
779
+ end
780
+
781
+
782
+ def Mode(mode = nil)
783
+ if mode
784
+ mode = mode.pack('L') if mode === Array
785
+ API.SetConsoleMode(@handle, mode)
786
+ else
787
+ return API.GetConsoleMode(@handle)
788
+ end
789
+ end
790
+
791
+ def WriteInput(*t)
792
+ API.WriteConsoleInput(@handle, *t)
793
+ end
794
+
795
+ def Attr(*attr)
796
+ if attr.size > 0
797
+ API.SetConsoleTextAttribute( @handle, attr[0] )
798
+ else
799
+ info = API.GetConsoleScreenBufferInfo( @handle )
800
+ return info[4]
801
+ end
802
+ end
803
+
804
+
805
+ def Size(*t)
806
+ if t.size == 0
807
+ col, row = API.GetConsoleScreenBufferInfo(@handle )
808
+ return [col, row]
809
+ else
810
+ row = -1 if !t[1]
811
+ col = -1 if !t[0]
812
+ if col < 0 or row < 0
813
+ curr_col, curr_row = Size()
814
+ col = curr_col if col < 0
815
+ row = curr_row if row < 0
816
+ end
817
+ API.SetConsoleScreenBufferSize(@handle, row, col)
818
+ end
819
+ end
820
+
821
+ def Window(*t)
822
+ if t.size != 5
823
+ info = API.GetConsoleScreenBufferInfo( @handle )
824
+ return info[5..8]
825
+ else
826
+ API.SetConsoleWindowInfo(@handle, t[0], t[1], t[2], t[3], t[4])
827
+ end
828
+ end
829
+
830
+ def FillAttr(attr, number = 1, col = -1, row = -1)
831
+ if col < 0 or row < 0
832
+ d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
833
+ col = curr_col if col < 0
834
+ row = curr_row if row < 0
835
+ end
836
+ API.FillConsoleOutputAttribute(@handle, attr, number, col, row)
837
+ end
838
+
839
+ def FillChar(char, number, col = -1, row = -1)
840
+ if col < 0 or row < 0
841
+ d, d, curr_col, curr_row = API.GetConsoleScreenBufferInfo(@handle)
842
+ col = curr_col if col < 0
843
+ row = curr_row if row < 0
844
+ end
845
+ API.FillConsoleOutputCharacter(@handle, char[0], number, col, row)
846
+ end
847
+
848
+ def Cls()
849
+ attr = ATTR_NORMAL
850
+ x, y = Size()
851
+ left, top, right , bottom = Window()
852
+ vx = right - left
853
+ vy = bottom - top
854
+ FillChar(' ', x*y, 0, 0)
855
+ FillAttr(attr, x*y, 0, 0)
856
+ Cursor(0,0)
857
+ Window(1,0,0,vx,vy)
858
+ end
859
+
860
+ def Console.Free()
861
+ API.FreeConsole()
862
+ end
863
+
864
+ def Console.Alloc()
865
+ API.AllocConsole()
866
+ end
867
+
868
+ def Console.MouseButtons()
869
+ API.GetNumberOfConsoleMouseButtons()
870
+ end
871
+
872
+ def Console.InputCP(codepage=nil)
873
+ if codepage
874
+ API.SetConsoleCP(codepage)
875
+ else
876
+ return API.GetConsoleCP()
877
+ end
878
+ end
879
+
880
+ def Console.OutputCP(codepage=nil)
881
+ if codepage
882
+ API.SetConsoleOutputCP(codepage)
883
+ else
884
+ return API.GetConsoleOutputCP()
885
+ end
886
+ end
887
+
888
+ def Console.GenerateCtrlEvent( type=nil, pid=nil )
889
+ type = API.constant('CTRL_C_EVENT') if type == nil
890
+ pid = 0 if pid == nil
891
+ API.GenerateConsoleCtrlEvent(type, pid)
892
+ end
893
+
894
+ end
895
+ end
896
+
897
+
898
+
899
+
900
+
901
+ FG_BLACK = 0
902
+ FG_BLUE = Win32::Console::API.constant("FOREGROUND_BLUE")
903
+ FG_LIGHTBLUE = Win32::Console::API.constant("FOREGROUND_BLUE")|
904
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
905
+ FG_RED = Win32::Console::API.constant("FOREGROUND_RED")
906
+ FG_LIGHTRED = Win32::Console::API.constant("FOREGROUND_RED")|
907
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
908
+ FG_GREEN = Win32::Console::API.constant("FOREGROUND_GREEN")
909
+ FG_LIGHTGREEN = Win32::Console::API.constant("FOREGROUND_GREEN")|
910
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
911
+ FG_MAGENTA = Win32::Console::API.constant("FOREGROUND_RED")|
912
+ Win32::Console::API.constant("FOREGROUND_BLUE")
913
+ FG_LIGHTMAGENTA = Win32::Console::API.constant("FOREGROUND_RED")|
914
+ Win32::Console::API.constant("FOREGROUND_BLUE")|
915
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
916
+ FG_CYAN = Win32::Console::API.constant("FOREGROUND_GREEN")|
917
+ Win32::Console::API.constant("FOREGROUND_BLUE")
918
+ FG_LIGHTCYAN = Win32::Console::API.constant("FOREGROUND_GREEN")|
919
+ Win32::Console::API.constant("FOREGROUND_BLUE")|
920
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
921
+ FG_BROWN = Win32::Console::API.constant("FOREGROUND_RED")|
922
+ Win32::Console::API.constant("FOREGROUND_GREEN")
923
+ FG_YELLOW = Win32::Console::API.constant("FOREGROUND_RED")|
924
+ Win32::Console::API.constant("FOREGROUND_GREEN")|
925
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
926
+ FG_GRAY = Win32::Console::API.constant("FOREGROUND_RED")|
927
+ Win32::Console::API.constant("FOREGROUND_GREEN")|
928
+ Win32::Console::API.constant("FOREGROUND_BLUE")
929
+ FG_WHITE = Win32::Console::API.constant("FOREGROUND_RED")|
930
+ Win32::Console::API.constant("FOREGROUND_GREEN")|
931
+ Win32::Console::API.constant("FOREGROUND_BLUE")|
932
+ Win32::Console::API.constant("FOREGROUND_INTENSITY")
933
+
934
+ BG_BLACK = 0
935
+ BG_BLUE = Win32::Console::API.constant("BACKGROUND_BLUE")
936
+ BG_LIGHTBLUE = Win32::Console::API.constant("BACKGROUND_BLUE")|
937
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
938
+ BG_RED = Win32::Console::API.constant("BACKGROUND_RED")
939
+ BG_LIGHTRED = Win32::Console::API.constant("BACKGROUND_RED")|
940
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
941
+ BG_GREEN = Win32::Console::API.constant("BACKGROUND_GREEN")
942
+ BG_LIGHTGREEN = Win32::Console::API.constant("BACKGROUND_GREEN")|
943
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
944
+ BG_MAGENTA = Win32::Console::API.constant("BACKGROUND_RED")|
945
+ Win32::Console::API.constant("BACKGROUND_BLUE")
946
+ BG_LIGHTMAGENTA = Win32::Console::API.constant("BACKGROUND_RED")|
947
+ Win32::Console::API.constant("BACKGROUND_BLUE")|
948
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
949
+ BG_CYAN = Win32::Console::API.constant("BACKGROUND_GREEN")|
950
+ Win32::Console::API.constant("BACKGROUND_BLUE")
951
+ BG_LIGHTCYAN = Win32::Console::API.constant("BACKGROUND_GREEN")|
952
+ Win32::Console::API.constant("BACKGROUND_BLUE")|
953
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
954
+ BG_BROWN = Win32::Console::API.constant("BACKGROUND_RED")|
955
+ Win32::Console::API.constant("BACKGROUND_GREEN")
956
+ BG_YELLOW = Win32::Console::API.constant("BACKGROUND_RED")|
957
+ Win32::Console::API.constant("BACKGROUND_GREEN")|
958
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
959
+ BG_GRAY = Win32::Console::API.constant("BACKGROUND_RED")|
960
+ Win32::Console::API.constant("BACKGROUND_GREEN")|
961
+ Win32::Console::API.constant("BACKGROUND_BLUE")
962
+ BG_WHITE = Win32::Console::API.constant("BACKGROUND_RED")|
963
+ Win32::Console::API.constant("BACKGROUND_GREEN")|
964
+ Win32::Console::API.constant("BACKGROUND_BLUE")|
965
+ Win32::Console::API.constant("BACKGROUND_INTENSITY")
966
+
967
+ ATTR_NORMAL = FG_GRAY | BG_BLACK
968
+ ATTR_INVERSE = FG_BLACK | BG_GRAY
969
+
970
+ include Win32::Console::Constants