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.
- data/CHANGES.txt +36 -0
- data/README.textile +162 -0
- data/Rakefile +88 -0
- data/bin/stella +12 -0
- data/bin/stella.bat +12 -0
- data/lib/daemonize.rb +56 -0
- data/lib/pcaplet.rb +180 -0
- data/lib/stella.rb +101 -0
- data/lib/stella/adapter/ab.rb +337 -0
- data/lib/stella/adapter/base.rb +106 -0
- data/lib/stella/adapter/httperf.rb +305 -0
- data/lib/stella/adapter/pcap_watcher.rb +221 -0
- data/lib/stella/adapter/proxy_watcher.rb +76 -0
- data/lib/stella/adapter/siege.rb +341 -0
- data/lib/stella/cli.rb +258 -0
- data/lib/stella/cli/agents.rb +73 -0
- data/lib/stella/cli/base.rb +55 -0
- data/lib/stella/cli/language.rb +18 -0
- data/lib/stella/cli/localtest.rb +78 -0
- data/lib/stella/cli/sysinfo.rb +16 -0
- data/lib/stella/cli/watch.rb +278 -0
- data/lib/stella/command/base.rb +40 -0
- data/lib/stella/command/localtest.rb +358 -0
- data/lib/stella/data/domain.rb +82 -0
- data/lib/stella/data/http.rb +131 -0
- data/lib/stella/logger.rb +84 -0
- data/lib/stella/response.rb +85 -0
- data/lib/stella/storable.rb +201 -0
- data/lib/stella/support.rb +276 -0
- data/lib/stella/sysinfo.rb +257 -0
- data/lib/stella/test/definition.rb +79 -0
- data/lib/stella/test/run/summary.rb +70 -0
- data/lib/stella/test/stats.rb +114 -0
- data/lib/stella/text.rb +64 -0
- data/lib/stella/text/resource.rb +38 -0
- data/lib/utils/crypto-key.rb +84 -0
- data/lib/utils/domainutil.rb +47 -0
- data/lib/utils/escape.rb +302 -0
- data/lib/utils/fileutil.rb +78 -0
- data/lib/utils/httputil.rb +266 -0
- data/lib/utils/mathutil.rb +15 -0
- data/lib/utils/stats.rb +88 -0
- data/lib/utils/textgraph.rb +267 -0
- data/lib/utils/timerutil.rb +58 -0
- data/lib/win32/Console.rb +970 -0
- data/lib/win32/Console/ANSI.rb +305 -0
- data/support/kvm.h +91 -0
- data/support/ruby-pcap-takuma-notes.txt +19 -0
- data/support/ruby-pcap-takuma-patch.txt +30 -0
- data/support/text/en.yaml +80 -0
- data/support/text/nl.yaml +7 -0
- data/support/useragents.txt +75 -0
- data/tests/01-util_test.rb +0 -0
- data/tests/02-stella-util_test.rb +42 -0
- data/tests/10-stella_test.rb +104 -0
- data/tests/11-stella-storable_test.rb +68 -0
- data/tests/60-stella-command_test.rb +248 -0
- data/tests/80-stella-cli_test.rb +45 -0
- data/tests/spec-helper.rb +31 -0
- metadata +165 -0
data/lib/utils/stats.rb
ADDED
@@ -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
|