win32console 1.3.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,119 @@
1
+ === 1.3.0.beta
2
+
3
+ * Enhancements
4
+ * Usage of Hoe and rake-compiler to ease releasing and extension
5
+ compilation.
6
+
7
+ * Bugfixes:
8
+ * Works with Ruby 1.9
9
+
10
+ * Known issues:
11
+ * win32console no longer automatically translate encoding to the console
12
+ output enconding. Please use Iconv to convert from your encoding (eg. UTF8)
13
+ to current console output:
14
+
15
+ current_cp = Win32::Console::OutputCP()
16
+ Iconv.iconv("cp#{current_cp}", "utf-8", utf_string)
17
+
18
+ A working example can be seen here: http://gist.github.com/265593
19
+
20
+ === 1.2.0 / 2008-11-22
21
+
22
+ * Enhancements
23
+ * Better code organization and clenaup
24
+
25
+ * Bugfixes:
26
+ * Removed license conflicting ANSI Term code and functionality.
27
+
28
+ === 1.1.0 / 2008-03-17
29
+
30
+ * Enhancements:
31
+ * Added Kernel#putc
32
+ Redefined Kernel#putc to wrap Win32::Console::ANSI::IO#putc
33
+
34
+ * Added #putc to Win32::Console::ANSI::IO
35
+ This putc buffers escape sequences so that they will be handled properly
36
+
37
+ * Added #redirected? to Win32::Console::ANSI::IO
38
+ Checks the mode of the console to see if IO is being redirected or not
39
+
40
+ * Added Win32::Console::API#WriteFile
41
+ to both the Ruby and compiled versions
42
+
43
+ * Added Win32::Console#WriteFile
44
+ This is a wrapper around Win32::Console::API#WriteFile
45
+
46
+ * Split Win32::Console::Constants and Win32::Console::API out into
47
+ seperate files. These two classes were in 'Win32/Console.rb'
48
+ I moved them into 'Win32/Console/constants.rb' and 'Win32/Console/api.rb'
49
+ respectively.
50
+
51
+ * Cleaned up indentation
52
+ indentations was a mixture of tabs and spaces. I made everything indented
53
+ with 2 spaces.
54
+
55
+ * Bugfixes:
56
+ * Fixed "Invalid Handle" error in compiled version of GetConsoleMode
57
+ I'm actually not sure of the source of this error.
58
+ It may be expected behavior when output is being redirected.
59
+ I worked around it by rescuing the exception in Win32::Console#Mode and
60
+ returning 9999. I picked that arbitrary value, because it is
61
+ higher than 31, which is what I think is the highest value Mode would
62
+ return if output isn't being redirected.
63
+ [Gordon Thiesfeld]
64
+
65
+ * Modified Win32::Console::ANSI::IO#write to check for redirection.
66
+ If output is redirected, it uses WriteFile instead of WriteConosle.
67
+ It also skips the parsing step, and passes the escape sequences through.
68
+ [Gordon Thiesfeld]
69
+
70
+ * Modified Win32::Console::ANSI::IO#_PrintString
71
+ Didn't change behavior, just tried to make it more idiomatic ruby.
72
+ I didn't make all of the changes I wanted to, because I wasn't sure
73
+ how to test them all.
74
+ [Gordon Thiesfeld]
75
+
76
+ * Modified all Win32::Console::API methods
77
+ [Gordon Thiesfeld]
78
+
79
+ It was assigning Win32API functions to class variables. I switched them to instance variables. I also changed the idiom it was using to instantiate the objects.
80
+ For instance, instead of:
81
+
82
+ if @@m_AllocConsole == nil
83
+ @@m_AllocConsole = Win32API.new( "kernel32", "AllocConsole",
84
+ [], 'l' )
85
+
86
+ It is now:
87
+
88
+ @AllocConsole ||= Win32API.new( "kernel32", "AllocConsole", [], 'l' )
89
+
90
+ * Non-string arguments passed to Win32::Console::ANSI#write caused error
91
+ fix by Ivan Evtuhovich (evtuhovich at gmail dot com).
92
+
93
+ === 1.0.8 / 2006-06-05
94
+
95
+ * New features:
96
+ * First public release of win32console gem by Justin Bailey.
97
+
98
+ === 1.0
99
+
100
+ * New features:
101
+ * Added .dup to _printString function to avoid mangling outside
102
+ string references. Removed the other (later) .dup call.
103
+
104
+ * Bugfixes:
105
+ * Turned of some exceptions that were conflicting with using the module
106
+ with pipes or redirections.
107
+
108
+ === 0.8
109
+
110
+ * Enhancements:
111
+ * Added ruby docs, and sample test suite.
112
+
113
+ * Bugfixes:
114
+ * Fixed bugs in reading routines,
115
+
116
+ === 0.5
117
+
118
+ New features:
119
+ * First public release.
data/Manifest.txt ADDED
@@ -0,0 +1,22 @@
1
+ History.txt
2
+ Manifest.txt
3
+ Rakefile
4
+ README.txt
5
+ ext/Console_ext/Console.c
6
+ ext/Console_ext/extconf.rb
7
+ extra/Console.rdoc
8
+ extra/Console_ANSI.rdoc
9
+ lib/win32console.rb
10
+ lib/Win32/Console.rb
11
+ lib/Win32/Console/ANSI.rb
12
+ lib/Win32/Console/api.rb
13
+ lib/Win32/Console/constants.rb
14
+ tasks/gem.rake
15
+ tasks/native.rake
16
+ test/test_cursor.rb
17
+ test/test_mouse.rb
18
+ test/test_readinput.rb
19
+ test/test_readoutput.rb
20
+ test/test_sendevent.rb
21
+ test/test_title.rb
22
+ test/test_write.rb
data/README.txt ADDED
@@ -0,0 +1,63 @@
1
+ = Win32::Console
2
+
3
+ * http://rubyforge.org/projects/winconsole
4
+ * http://github.com/luislavena/win32console
5
+ * http://rdoc.info/projects/luislavena/win32console
6
+
7
+ == DESCRIPTION
8
+
9
+ Win32::Console allows controling the windows command line terminal
10
+ thru an OO-interface. This allows you to query the terminal (find
11
+ its size, characters, attributes, etc). The interface and functionality
12
+ should be identical to Perl's counterpart.
13
+
14
+ A port of Perl's Win32::Console and Win32::Console::ANSI modules.
15
+
16
+ This gem packages Gonzalo Garramuno's Win32::Console project, and includes
17
+ a compiled binary for speed. The Win32::Console project's home can be
18
+ found at:
19
+
20
+ http://rubyforge.org/projects/win32console
21
+
22
+ == FEATURES
23
+
24
+ Win32::Console::ANSI is a class derived from IO that seamlessly
25
+ translates ANSI Esc control character codes into Windows' command.exe
26
+ or cmd.exe equivalents.
27
+
28
+ To ease usage, you can use in combination with term-ansicolor gem and avoid
29
+ writing ANSI codes manually.
30
+
31
+ == EXAMPLES
32
+
33
+ To output a simple bolded string, try this script:
34
+
35
+ require 'rubygems'
36
+ require 'win32console'
37
+ include Win32::Console::ANSI
38
+ include Term::ANSIColor
39
+
40
+ puts bold << "bolded text" << clear << " and no longer bold."
41
+
42
+ == INSTALL
43
+
44
+ gem install win32console
45
+
46
+ == DEVELOPERS:
47
+
48
+ After checking out the source, run:
49
+
50
+ $ rake newb
51
+
52
+ This task will install any missing dependencies, run the tests/specs,
53
+ and generate the RDoc.
54
+
55
+ == LICENSE
56
+
57
+ This program is FREE; you can redistribute, modify, disassemble, or even
58
+ reverse engineer this software at your will. Keep in mind, however, that
59
+ NOTHING IS GUARANTEED to work and everything you do is AT YOUR OWN RISK - I
60
+ will not take responsibility for any damage, loss of money and/or health
61
+ that may arise from the use of this program!
62
+
63
+ This is distributed under the terms of Larry Wall's Artistic License.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ #
2
+ # NOTE: Keep this file clean.
3
+ # Add your customizations inside tasks directory.
4
+ # Thank You.
5
+ #
6
+
7
+ # load rakefile extensions (tasks)
8
+ Dir['tasks/*.rake'].sort.each { |f| load f }
9
+
10
+ =begin
11
+ require 'rubygems'
12
+ require 'rake/clean'
13
+ require 'rake/gempackagetask'
14
+ require 'rake/extensiontask'
15
+
16
+ spec = Gem::Specification.new do |s|
17
+ s.name = 'win32console'
18
+ s.version = '1.2.0'
19
+ s.platform = Gem::Platform::RUBY
20
+ s.has_rdoc = true
21
+ s.extra_rdoc_files = %w[ README.txt README_GEM.txt INSTALL.txt HISTORY.txt HISTORY_GEM.txt ]
22
+ s.summary = 'A library giving the Win32 console ANSI escape sequence support.'
23
+ s.description = s.summary
24
+ s.author = 'Original Library by Gonzalo Garramuno, Gem by Justin Bailey'
25
+ s.email = 'ggarra @nospam@ advancedsl.com.ar, jgbailey @nospan@ gmail.com'
26
+ s.homepage = 'http://rubyforge.org/projects/winconsole'
27
+ s.rubyforge_project = 'http://rubyforge.org/projects/winconsole'
28
+ s.description = <<EOS
29
+ This gem packages Gonzalo Garramuno's Win32::Console project, and includes a compiled binary for speed. The Win32::Console project's home can be found at:
30
+
31
+ http://rubyforge.org/projects/win32console
32
+
33
+ The gem project can be found at
34
+
35
+ http://rubyforge.org/projects/winconsole
36
+ EOS
37
+
38
+ s.require_path = 'lib'
39
+ s.extensions = %w[ ext/Console/extconf.rb ]
40
+ s.files = FileList[ '{doc,ext,lib,test}/**/*.{rdoc,c,cpp,rb}', 'Rakefile', *s.extra_rdoc_files ]
41
+
42
+ s.rdoc_options << '--title' << 'Win32Console Gem -- Gem for Win32::Console Project' <<
43
+ '--main' << 'README_GEM.txt' <<
44
+ '--line-numbers'
45
+ end
46
+
47
+ Rake::GemPackageTask.new(spec) do |pkg|
48
+ pkg.need_tar = true
49
+ pkg.gem_spec = spec
50
+ end
51
+
52
+ Rake::ExtensionTask.new('Console', spec) do |ext|
53
+ end
54
+ =end
@@ -0,0 +1,1216 @@
1
+ #include <windows.h>
2
+ #include "ruby.h"
3
+
4
+ /* Workaround deprecated RString accessors */
5
+ #ifndef RSTRING_PTR
6
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
7
+ #endif
8
+ #ifndef RSTRING_LEN
9
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
10
+ #endif
11
+
12
+ VALUE rb_mWin32;
13
+ VALUE rb_mConsole;
14
+ VALUE rb_mAPI;
15
+ VALUE rb_mConstants;
16
+
17
+ /* old RUBY_METHOD_FUNC() definition doesn't match to prototypes in those days. */
18
+ #ifndef ANYARGS
19
+ #undef RUBY_METHOD_FUNC
20
+ #define RUBY_METHOD_FUNC(func) ((VALUE (*)())func)
21
+ #endif
22
+
23
+
24
+ #define RB_DEF_S_METHOD(klass,method,func,argtype) \
25
+ rb_define_singleton_method(klass,method,RUBY_METHOD_FUNC(func), argtype)
26
+
27
+ #define RB_DEF_API_METHOD(name,argtype) \
28
+ RB_DEF_S_METHOD(rb_mAPI,#name,RUBY_METHOD_FUNC(rb_##name), argtype)
29
+
30
+ #define RB_DEF_METHOD(klass,method,func,argtype) \
31
+ rb_define_method(klass,method,RUBY_METHOD_FUNC(func), argtype)
32
+
33
+ VALUE
34
+ rb_getWin32Error()
35
+ {
36
+ LPVOID lpMsgBuf;
37
+ if (!FormatMessage(
38
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
39
+ FORMAT_MESSAGE_FROM_SYSTEM |
40
+ FORMAT_MESSAGE_IGNORE_INSERTS,
41
+ NULL,
42
+ GetLastError(),
43
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
44
+ (LPTSTR) &lpMsgBuf,
45
+ 0,
46
+ NULL ))
47
+ {
48
+ // Handle the error.
49
+ return Qnil;
50
+ }
51
+
52
+ VALUE t = rb_str_new2( (LPCTSTR) lpMsgBuf );
53
+
54
+ // Free the buffer.
55
+ LocalFree( lpMsgBuf );
56
+
57
+ // Raise exception
58
+ rb_raise(rb_eRuntimeError, RSTRING_PTR(t));
59
+ return Qnil;
60
+
61
+ }
62
+
63
+
64
+ static VALUE rb_GetStdHandle(VALUE self, VALUE handle)
65
+ {
66
+ unsigned long x;
67
+ if ( FIXNUM_P( handle ) )
68
+ {
69
+ x = NUM2ULONG( handle );
70
+ }
71
+ else
72
+ {
73
+ Check_Type( handle, T_BIGNUM );
74
+ x = rb_big2ulong(handle);
75
+ }
76
+ unsigned long h = PtrToUlong( GetStdHandle( x ) );
77
+ return ULONG2NUM(h);
78
+ }
79
+
80
+
81
+ static VALUE rb_AllocConsole(VALUE self)
82
+ {
83
+ if (AllocConsole()) return INT2FIX(1);
84
+ return rb_getWin32Error();
85
+ }
86
+
87
+
88
+ static VALUE rb_FreeConsole(VALUE self)
89
+ {
90
+ if (FreeConsole()) return INT2FIX(1);
91
+ return rb_getWin32Error();
92
+ }
93
+
94
+ static VALUE rb_GenerateConsoleCtrlEvent(VALUE self, VALUE event, VALUE pgid)
95
+ {
96
+ unsigned int e = NUM2UINT(event);
97
+ if ( e != CTRL_C_EVENT && e != CTRL_BREAK_EVENT )
98
+ rb_raise(rb_eArgError, "Wrong event: only CTRL_C_EVENT or "
99
+ "CTRL_BREAK_EVENT accepted.");
100
+ if ( GenerateConsoleCtrlEvent(e, NUM2UINT(pgid)) )
101
+ return INT2FIX(1);
102
+ return rb_getWin32Error();
103
+ }
104
+
105
+ static VALUE rb_GetConsoleMode(VALUE self, VALUE hConsoleOutput)
106
+ {
107
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
108
+ DWORD mode;
109
+ if (GetConsoleMode(handle,&mode))
110
+ return UINT2NUM(mode);
111
+ return rb_getWin32Error();
112
+ }
113
+
114
+ static VALUE rb_GetConsoleTitle(VALUE self)
115
+ {
116
+ char title[1024];
117
+ if (GetConsoleTitle((char*)&title,1024))
118
+ return rb_str_new2( title );
119
+ return rb_getWin32Error();
120
+ }
121
+
122
+
123
+
124
+
125
+ static VALUE rb_GetNumberOfConsoleMouseButtons( VALUE self )
126
+ {
127
+ DWORD mb;
128
+ if (GetNumberOfConsoleMouseButtons( &mb ))
129
+ return INT2FIX(mb);
130
+ return rb_getWin32Error();
131
+ }
132
+
133
+
134
+
135
+ static VALUE rb_GetNumberOfConsoleInputEvents( VALUE self, VALUE hConsoleOutput )
136
+ {
137
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
138
+ DWORD events;
139
+ if (GetNumberOfConsoleInputEvents(handle, &events))
140
+ return INT2FIX(events);
141
+ return rb_getWin32Error();
142
+ }
143
+
144
+
145
+ static VALUE
146
+ rb_CreateConsoleScreenBuffer( VALUE self, VALUE dwDesiredAccess,
147
+ VALUE dwShareMode, VALUE dwFlags )
148
+ {
149
+ if (CreateConsoleScreenBuffer( NUM2UINT(dwDesiredAccess),
150
+ NUM2UINT( dwShareMode),
151
+ NULL,
152
+ NUM2UINT( dwFlags),
153
+ NULL
154
+ ))
155
+ return INT2FIX(1);
156
+ return rb_getWin32Error();
157
+ }
158
+
159
+
160
+ static VALUE rb_GetConsoleCP( VALUE self )
161
+ {
162
+ unsigned int h = GetConsoleCP();
163
+ return UINT2NUM(h);
164
+ }
165
+
166
+ static VALUE rb_GetConsoleOutputCP( VALUE self )
167
+ {
168
+ unsigned int h = GetConsoleOutputCP();
169
+ return UINT2NUM(h);
170
+ }
171
+
172
+ static VALUE rb_SetConsoleMode( VALUE self, VALUE hConsoleOutput,
173
+ VALUE Mode )
174
+ {
175
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
176
+ if ( SetConsoleMode( handle, NUM2UINT( Mode ) ) )
177
+ return INT2FIX(1);
178
+ return rb_getWin32Error();
179
+ }
180
+
181
+ static VALUE rb_SetConsoleCP( VALUE self, VALUE wCodePageID )
182
+ {
183
+ if ( SetConsoleCP( NUM2UINT( wCodePageID ) ) )
184
+ return INT2FIX(1);
185
+ return rb_getWin32Error();
186
+ }
187
+
188
+ static VALUE rb_SetConsoleOutputCP( VALUE self, VALUE wCodePageID )
189
+ {
190
+ if ( SetConsoleOutputCP( NUM2UINT( wCodePageID ) ) )
191
+ return INT2FIX(1);
192
+ return rb_getWin32Error();
193
+ }
194
+
195
+ static VALUE rb_GetConsoleWindow( VALUE self )
196
+ {
197
+ unsigned long h = PtrToUlong( GetConsoleOutputCP() );
198
+ return ULONG2NUM(h);
199
+ }
200
+
201
+ static VALUE rb_WriteConsole( VALUE self, VALUE hConsoleOutput,
202
+ VALUE lpBuffer )
203
+ {
204
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
205
+ DWORD nNumberOfCharsToWrite = RSTRING_LEN(lpBuffer);
206
+
207
+ DWORD lpNumberOfCharsWritten;
208
+
209
+ WriteConsole( handle, RSTRING_PTR(lpBuffer),
210
+ nNumberOfCharsToWrite,
211
+ &lpNumberOfCharsWritten, NULL );
212
+ return UINT2NUM( lpNumberOfCharsWritten );
213
+ }
214
+
215
+ static VALUE rb_WriteFile( VALUE self, VALUE hConsoleOutput,
216
+ VALUE lpBuffer )
217
+ {
218
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
219
+ DWORD nNumberOfBytesToWrite = RSTRING_LEN(lpBuffer);
220
+
221
+ DWORD lpNumberOfBytesWritten;
222
+
223
+ WriteFile( handle, RSTRING_PTR(lpBuffer),
224
+ nNumberOfBytesToWrite,
225
+ &lpNumberOfBytesWritten, NULL );
226
+ return UINT2NUM( lpNumberOfBytesWritten );
227
+ }
228
+
229
+
230
+ static VALUE rb_GetLargestConsoleWindowSize( VALUE self, VALUE hConsoleOutput )
231
+ {
232
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
233
+ COORD size = GetLargestConsoleWindowSize( handle);
234
+
235
+ VALUE ret = rb_ary_new();
236
+ rb_ary_push( ret, UINT2NUM( size.X ) );
237
+ rb_ary_push( ret, UINT2NUM( size.Y ) );
238
+ return ret;
239
+ }
240
+
241
+ static VALUE rb_GetConsoleCursorInfo( VALUE self, VALUE hConsoleOutput )
242
+ {
243
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
244
+
245
+ CONSOLE_CURSOR_INFO out;
246
+ if ( !GetConsoleCursorInfo( handle, &out ) )
247
+ return rb_getWin32Error();
248
+
249
+ VALUE ret = rb_ary_new();
250
+ rb_ary_push( ret, UINT2NUM( out.dwSize ) );
251
+ rb_ary_push( ret, UINT2NUM( out.bVisible ) );
252
+ return ret;
253
+ }
254
+
255
+ void rb_ParseEvent(VALUE ret, INPUT_RECORD *event )
256
+ {
257
+ switch(event->EventType) {
258
+ case KEY_EVENT:
259
+ {
260
+ KEY_EVENT_RECORD* kevent=(KEY_EVENT_RECORD *)&(event->Event);
261
+ rb_ary_push(ret, UINT2NUM(KEY_EVENT));
262
+ rb_ary_push(ret, UINT2NUM(kevent->bKeyDown));
263
+ rb_ary_push(ret, UINT2NUM(kevent->wRepeatCount));
264
+ rb_ary_push(ret, UINT2NUM(kevent->wVirtualKeyCode));
265
+ rb_ary_push(ret, UINT2NUM(kevent->wVirtualScanCode));
266
+ #ifdef UNICODE
267
+ rb_ary_push(ret, UINT2NUM(kevent->uChar.UnicodeChar));
268
+ #else
269
+ rb_ary_push(ret, UINT2NUM(kevent->uChar.AsciiChar));
270
+ #endif
271
+ rb_ary_push(ret, UINT2NUM(kevent->dwControlKeyState));
272
+ break;
273
+ }
274
+ case MOUSE_EVENT:
275
+ {
276
+ MOUSE_EVENT_RECORD * mevent=(MOUSE_EVENT_RECORD *)&(event->Event);
277
+ rb_ary_push(ret, UINT2NUM(MOUSE_EVENT) );
278
+ rb_ary_push(ret, UINT2NUM(mevent->dwMousePosition.X) );
279
+ rb_ary_push(ret, UINT2NUM(mevent->dwMousePosition.Y) );
280
+ rb_ary_push(ret, UINT2NUM(mevent->dwButtonState) );
281
+ rb_ary_push(ret, UINT2NUM(mevent->dwControlKeyState) );
282
+ rb_ary_push(ret, UINT2NUM(mevent->dwEventFlags) );
283
+ break;
284
+ }
285
+ case WINDOW_BUFFER_SIZE_EVENT:
286
+ {
287
+ WINDOW_BUFFER_SIZE_RECORD* wevent=
288
+ (WINDOW_BUFFER_SIZE_RECORD *)&(event->Event);
289
+ rb_ary_push(ret, UINT2NUM(WINDOW_BUFFER_SIZE_EVENT) );
290
+ rb_ary_push(ret, UINT2NUM(wevent->dwSize.X) );
291
+ rb_ary_push(ret, UINT2NUM(wevent->dwSize.Y) );
292
+ }
293
+ break;
294
+ case MENU_EVENT:
295
+ {
296
+ MENU_EVENT_RECORD* mevent= (MENU_EVENT_RECORD *)&(event->Event);
297
+ rb_ary_push(ret, UINT2NUM(MENU_EVENT) );
298
+ rb_ary_push(ret, UINT2NUM(mevent->dwCommandId) );
299
+ }
300
+ break;
301
+ case FOCUS_EVENT:
302
+ {
303
+ FOCUS_EVENT_RECORD* mevent= (FOCUS_EVENT_RECORD *)&(event->Event);
304
+ rb_ary_push(ret, UINT2NUM(FOCUS_EVENT) );
305
+ rb_ary_push(ret, UINT2NUM(mevent->bSetFocus) );
306
+ }
307
+ break;
308
+ }
309
+ }
310
+
311
+ static VALUE rb_PeekConsoleInput( VALUE self, VALUE hConsoleOutput )
312
+ {
313
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
314
+
315
+ DWORD nofread;
316
+ INPUT_RECORD event;
317
+ if (!PeekConsoleInput(handle,&event,1,&nofread))
318
+ return rb_getWin32Error();
319
+
320
+ VALUE ret = rb_ary_new();
321
+ rb_ParseEvent( ret, &event );
322
+ return ret;
323
+ }
324
+
325
+ static VALUE rb_ReadConsole( VALUE self, VALUE hConsoleOutput,
326
+ VALUE buffer, VALUE numread )
327
+ {
328
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
329
+ DWORD nofread;
330
+ Check_Type( buffer, T_STRING );
331
+ int to_read = NUM2INT(numread);
332
+ if ( RSTRING_LEN(buffer) > to_read )
333
+ rb_raise(rb_eArgError, "String is too small to read that many characters.");
334
+ if (ReadConsole(handle,(void *)RSTRING_PTR(buffer), to_read,
335
+ &nofread,NULL))
336
+ return UINT2NUM(nofread);
337
+ return rb_getWin32Error();
338
+ }
339
+
340
+ static VALUE rb_ReadConsoleInput( VALUE self, VALUE hConsoleOutput )
341
+ {
342
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
343
+ DWORD nofread;
344
+ INPUT_RECORD event;
345
+ if (!ReadConsoleInput(handle,&event,1,&nofread))
346
+ return rb_getWin32Error();
347
+
348
+ VALUE ret = rb_ary_new();
349
+ rb_ParseEvent( ret, &event );
350
+ return ret;
351
+ }
352
+
353
+
354
+
355
+ static VALUE rb_ReadConsoleOutputCharacter( VALUE self, VALUE hConsoleOutput,
356
+ VALUE charbuf, VALUE len,
357
+ VALUE x, VALUE y )
358
+ {
359
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
360
+ COORD coords;
361
+ DWORD nofread;
362
+ coords.X= NUM2UINT( x );
363
+ coords.Y= NUM2UINT( y );
364
+ int l = NUM2INT(len);
365
+ if ( (unsigned long)RSTRING_LEN(charbuf) < l*sizeof(TCHAR) )
366
+ rb_raise(rb_eArgError, "String is too small to read that many characters.");
367
+ if (ReadConsoleOutputCharacter(handle,RSTRING_PTR(charbuf),l,
368
+ coords,&nofread))
369
+ return UINT2NUM( nofread );
370
+ return rb_getWin32Error();
371
+ }
372
+
373
+
374
+ static VALUE rb_ReadConsoleOutputAttribute( VALUE self, VALUE hConsoleOutput,
375
+ VALUE len, VALUE x, VALUE y )
376
+ {
377
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
378
+ COORD coords;
379
+ DWORD nofread;
380
+ unsigned short abuffer[80*999*sizeof(unsigned short)];
381
+ char cbuffer[80*999];
382
+ unsigned i = 0;
383
+
384
+ coords.X= NUM2UINT( x );
385
+ coords.Y= NUM2UINT( y );
386
+ if (ReadConsoleOutputAttribute(handle, abuffer, NUM2UINT(len),
387
+ coords,&nofread))
388
+ {
389
+ for(i=0;i<nofread;++i) {
390
+ cbuffer[i]=(char)abuffer[i];
391
+ }
392
+ return rb_str_new( cbuffer, nofread );
393
+ }
394
+ return rb_getWin32Error();
395
+ }
396
+
397
+
398
+ static VALUE rb_ReadConsoleOutput( VALUE self, VALUE hConsoleOutput,
399
+ VALUE buffer, VALUE srcwid, VALUE srcht,
400
+ VALUE startx, VALUE starty,
401
+ VALUE l, VALUE t, VALUE r, VALUE b )
402
+ {
403
+ COORD coords;
404
+ COORD size;
405
+ SMALL_RECT from;
406
+ size.X= NUM2UINT( srcwid );
407
+ size.Y= NUM2UINT( srcht );
408
+ coords.X= NUM2INT( startx );
409
+ coords.Y= NUM2INT( starty );
410
+ from.Left = NUM2INT( l );
411
+ from.Top = NUM2INT( t );
412
+ from.Right = NUM2INT( r );
413
+ from.Bottom = NUM2INT( b );
414
+ Check_Type( buffer, T_STRING );
415
+ if ( (unsigned long)RSTRING_LEN(buffer) < (sizeof(CHAR_INFO)*size.X*size.Y) )
416
+ rb_raise(rb_eArgError, "string buffer is too small for reading that many characters.");
417
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
418
+ if (!ReadConsoleOutput(handle,(CHAR_INFO *)RSTRING_PTR(buffer),size,coords,&from))
419
+ return rb_getWin32Error();
420
+
421
+ VALUE ret = rb_ary_new();
422
+ rb_ary_push( ret, INT2FIX(from.Left) );
423
+ rb_ary_push( ret, INT2FIX(from.Top) );
424
+ rb_ary_push( ret, INT2FIX(from.Right) );
425
+ rb_ary_push( ret, INT2FIX(from.Bottom) );
426
+ return ret;
427
+ }
428
+
429
+
430
+
431
+ static VALUE rb_GetConsoleScreenBufferInfo( VALUE self, VALUE hConsoleOutput )
432
+ {
433
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
434
+
435
+ CONSOLE_SCREEN_BUFFER_INFO out;
436
+
437
+ if ( !GetConsoleScreenBufferInfo( handle, &out ) )
438
+ return rb_getWin32Error();
439
+
440
+ VALUE ret = rb_ary_new();
441
+ rb_ary_push( ret, UINT2NUM( out.dwSize.X ) );
442
+ rb_ary_push( ret, UINT2NUM( out.dwSize.Y ) );
443
+ rb_ary_push( ret, UINT2NUM( out.dwCursorPosition.X ) );
444
+ rb_ary_push( ret, UINT2NUM( out.dwCursorPosition.Y ) );
445
+
446
+ rb_ary_push( ret, UINT2NUM( out.wAttributes ) );
447
+
448
+ rb_ary_push( ret, INT2FIX( out.srWindow.Left ) );
449
+ rb_ary_push( ret, INT2FIX( out.srWindow.Top ) );
450
+ rb_ary_push( ret, INT2FIX( out.srWindow.Right ) );
451
+ rb_ary_push( ret, INT2FIX( out.srWindow.Bottom ) );
452
+
453
+ rb_ary_push( ret, UINT2NUM( out.dwMaximumWindowSize.X ) );
454
+ rb_ary_push( ret, UINT2NUM( out.dwMaximumWindowSize.Y ) );
455
+
456
+
457
+ return ret;
458
+ }
459
+
460
+
461
+ #define strEQ(x,y) strcmp(x,y) == 0
462
+
463
+ DWORD c_constant(char *name)
464
+ {
465
+ switch (*name) {
466
+ case 'A':
467
+ break;
468
+ case 'B':
469
+ if (strEQ(name, "BACKGROUND_BLUE"))
470
+ #ifdef BACKGROUND_BLUE
471
+ return BACKGROUND_BLUE;
472
+ #else
473
+ goto not_there;
474
+ #endif
475
+ if (strEQ(name, "BACKGROUND_GREEN"))
476
+ #ifdef BACKGROUND_GREEN
477
+ return BACKGROUND_GREEN;
478
+ #else
479
+ goto not_there;
480
+ #endif
481
+ if (strEQ(name, "BACKGROUND_INTENSITY"))
482
+ #ifdef BACKGROUND_INTENSITY
483
+ return BACKGROUND_INTENSITY;
484
+ #else
485
+ goto not_there;
486
+ #endif
487
+ if (strEQ(name, "BACKGROUND_RED"))
488
+ #ifdef BACKGROUND_RED
489
+ return BACKGROUND_RED;
490
+ #else
491
+ goto not_there;
492
+ #endif
493
+ break;
494
+ case 'C':
495
+ if (strEQ(name, "CAPSLOCK_ON"))
496
+ #ifdef CAPSLOCK_ON
497
+ return CAPSLOCK_ON;
498
+ #else
499
+ goto not_there;
500
+ #endif
501
+ if (strEQ(name, "CONSOLE_TEXTMODE_BUFFER"))
502
+ #ifdef CONSOLE_TEXTMODE_BUFFER
503
+ return CONSOLE_TEXTMODE_BUFFER;
504
+ #else
505
+ goto not_there;
506
+ #endif
507
+ if (strEQ(name, "CTRL_BREAK_EVENT"))
508
+ #ifdef CTRL_BREAK_EVENT
509
+ return CTRL_BREAK_EVENT;
510
+ #else
511
+ goto not_there;
512
+ #endif
513
+ if (strEQ(name, "CTRL_C_EVENT"))
514
+ #ifdef CTRL_C_EVENT
515
+ return CTRL_C_EVENT;
516
+ #else
517
+ goto not_there;
518
+ #endif
519
+ break;
520
+
521
+ case 'D':
522
+ break;
523
+ case 'E':
524
+ if (strEQ(name, "ENABLE_ECHO_INPUT"))
525
+ #ifdef ENABLE_ECHO_INPUT
526
+ return ENABLE_ECHO_INPUT;
527
+ #else
528
+ goto not_there;
529
+ #endif
530
+ if (strEQ(name, "ENABLE_LINE_INPUT"))
531
+ #ifdef ENABLE_LINE_INPUT
532
+ return ENABLE_LINE_INPUT;
533
+ #else
534
+ goto not_there;
535
+ #endif
536
+ if (strEQ(name, "ENABLE_MOUSE_INPUT"))
537
+ #ifdef ENABLE_MOUSE_INPUT
538
+ return ENABLE_MOUSE_INPUT;
539
+ #else
540
+ goto not_there;
541
+ #endif
542
+ if (strEQ(name, "ENABLE_PROCESSED_INPUT"))
543
+ #ifdef ENABLE_PROCESSED_INPUT
544
+ return ENABLE_PROCESSED_INPUT;
545
+ #else
546
+ goto not_there;
547
+ #endif
548
+ if (strEQ(name, "ENABLE_PROCESSED_OUTPUT"))
549
+ #ifdef ENABLE_PROCESSED_OUTPUT
550
+ return ENABLE_PROCESSED_OUTPUT;
551
+ #else
552
+ goto not_there;
553
+ #endif
554
+ if (strEQ(name, "ENABLE_WINDOW_INPUT"))
555
+ #ifdef ENABLE_WINDOW_INPUT
556
+ return ENABLE_WINDOW_INPUT;
557
+ #else
558
+ goto not_there;
559
+ #endif
560
+ if (strEQ(name, "ENABLE_WRAP_AT_EOL_OUTPUT"))
561
+ #ifdef ENABLE_WRAP_AT_EOL_OUTPUT
562
+ return ENABLE_WRAP_AT_EOL_OUTPUT;
563
+ #else
564
+ goto not_there;
565
+ #endif
566
+ if (strEQ(name, "ENHANCED_KEY"))
567
+ #ifdef ENHANCED_KEY
568
+ return ENHANCED_KEY;
569
+ #else
570
+ goto not_there;
571
+ #endif
572
+ break;
573
+ case 'F':
574
+ if (strEQ(name, "FILE_SHARE_READ"))
575
+ #ifdef FILE_SHARE_READ
576
+ return FILE_SHARE_READ;
577
+ #else
578
+ goto not_there;
579
+ #endif
580
+ if (strEQ(name, "FILE_SHARE_WRITE"))
581
+ #ifdef FILE_SHARE_WRITE
582
+ return FILE_SHARE_WRITE;
583
+ #else
584
+ goto not_there;
585
+ #endif
586
+ if (strEQ(name, "FOREGROUND_BLUE"))
587
+ #ifdef FOREGROUND_BLUE
588
+ return FOREGROUND_BLUE;
589
+ #else
590
+ goto not_there;
591
+ #endif
592
+ if (strEQ(name, "FOREGROUND_GREEN"))
593
+ #ifdef FOREGROUND_GREEN
594
+ return FOREGROUND_GREEN;
595
+ #else
596
+ goto not_there;
597
+ #endif
598
+ if (strEQ(name, "FOREGROUND_INTENSITY"))
599
+ #ifdef FOREGROUND_INTENSITY
600
+ return FOREGROUND_INTENSITY;
601
+ #else
602
+ goto not_there;
603
+ #endif
604
+ if (strEQ(name, "FOREGROUND_RED"))
605
+ #ifdef FOREGROUND_RED
606
+ return FOREGROUND_RED;
607
+ #else
608
+ goto not_there;
609
+ #endif
610
+ break;
611
+ case 'G':
612
+ if (strEQ(name, "GENERIC_READ"))
613
+ #ifdef GENERIC_READ
614
+ return GENERIC_READ;
615
+ #else
616
+ goto not_there;
617
+ #endif
618
+ if (strEQ(name, "GENERIC_WRITE"))
619
+ #ifdef GENERIC_WRITE
620
+ return GENERIC_WRITE;
621
+ #else
622
+ goto not_there;
623
+ #endif
624
+ break;
625
+ case 'H':
626
+ break;
627
+ case 'I':
628
+ break;
629
+ case 'J':
630
+ break;
631
+ case 'K':
632
+ if (strEQ(name, "KEY_EVENT"))
633
+ #ifdef KEY_EVENT
634
+ return KEY_EVENT;
635
+ #else
636
+ goto not_there;
637
+ #endif
638
+ break;
639
+ case 'L':
640
+ if (strEQ(name, "LEFT_ALT_PRESSED"))
641
+ #ifdef LEFT_ALT_PRESSED
642
+ return LEFT_ALT_PRESSED;
643
+ #else
644
+ goto not_there;
645
+ #endif
646
+ if (strEQ(name, "LEFT_CTRL_PRESSED"))
647
+ #ifdef LEFT_CTRL_PRESSED
648
+ return LEFT_CTRL_PRESSED;
649
+ #else
650
+ goto not_there;
651
+ #endif
652
+ break;
653
+ case 'M':
654
+ break;
655
+ case 'N':
656
+ if (strEQ(name, "NUMLOCK_ON"))
657
+ #ifdef NUMLOCK_ON
658
+ return NUMLOCK_ON;
659
+ #else
660
+ goto not_there;
661
+ #endif
662
+ break;
663
+ case 'O':
664
+ break;
665
+ case 'P':
666
+ break;
667
+ case 'Q':
668
+ break;
669
+ case 'R':
670
+ if (strEQ(name, "RIGHT_ALT_PRESSED"))
671
+ #ifdef RIGHT_ALT_PRESSED
672
+ return RIGHT_ALT_PRESSED;
673
+ #else
674
+ goto not_there;
675
+ #endif
676
+ if (strEQ(name, "RIGHT_CTRL_PRESSED"))
677
+ #ifdef RIGHT_CTRL_PRESSED
678
+ return RIGHT_CTRL_PRESSED;
679
+ #else
680
+ goto not_there;
681
+ #endif
682
+ break;
683
+ case 'S':
684
+ if (strEQ(name, "SCROLLLOCK_ON"))
685
+ #ifdef SCROLLLOCK_ON
686
+ return SCROLLLOCK_ON;
687
+ #else
688
+ goto not_there;
689
+ #endif
690
+ if (strEQ(name, "SHIFT_PRESSED"))
691
+ #ifdef SHIFT_PRESSED
692
+ return SHIFT_PRESSED;
693
+ #else
694
+ goto not_there;
695
+ #endif
696
+ if (strEQ(name, "STD_ERROR_HANDLE"))
697
+ #ifdef STD_ERROR_HANDLE
698
+ return STD_ERROR_HANDLE;
699
+ #else
700
+ goto not_there;
701
+ #endif
702
+ if (strEQ(name, "STD_INPUT_HANDLE"))
703
+ #ifdef STD_INPUT_HANDLE
704
+ return STD_INPUT_HANDLE;
705
+ #else
706
+ goto not_there;
707
+ #endif
708
+ if (strEQ(name, "STD_OUTPUT_HANDLE"))
709
+ #ifdef STD_OUTPUT_HANDLE
710
+ return STD_OUTPUT_HANDLE;
711
+ #else
712
+ goto not_there;
713
+ #endif
714
+ break;
715
+ case 'T':
716
+ break;
717
+ case 'U':
718
+ break;
719
+ case 'V':
720
+ break;
721
+ case 'W':
722
+ break;
723
+ case 'X':
724
+ break;
725
+ case 'Y':
726
+ break;
727
+ case 'Z':
728
+ break;
729
+ }
730
+ rb_raise(rb_eArgError, "Not such constant.");
731
+ return 0;
732
+
733
+ not_there:
734
+ rb_raise(rb_eArgError, "Not defined.");
735
+ return 0;
736
+ }
737
+
738
+ VALUE rb_constant( VALUE self, VALUE name )
739
+ {
740
+ Check_Type( name, T_STRING );
741
+ return ULONG2NUM( c_constant( RSTRING_PTR(name) ) );
742
+ }
743
+
744
+
745
+ void define_constants()
746
+ {
747
+ #define DEF_SELF_CONST(NAME) \
748
+ rb_define_const(rb_mConstants, #NAME, ULONG2NUM( (ULONG)NAME ) );
749
+
750
+ DEF_SELF_CONST( STD_INPUT_HANDLE );
751
+ DEF_SELF_CONST( STD_OUTPUT_HANDLE );
752
+ DEF_SELF_CONST( STD_ERROR_HANDLE );
753
+ DEF_SELF_CONST( INVALID_HANDLE_VALUE );
754
+ DEF_SELF_CONST( GENERIC_READ );
755
+ DEF_SELF_CONST( GENERIC_WRITE );
756
+ DEF_SELF_CONST( FILE_SHARE_READ );
757
+ DEF_SELF_CONST( FILE_SHARE_WRITE );
758
+ DEF_SELF_CONST( CONSOLE_TEXTMODE_BUFFER );
759
+
760
+ DEF_SELF_CONST( FOREGROUND_BLUE );
761
+ DEF_SELF_CONST( FOREGROUND_GREEN );
762
+ DEF_SELF_CONST( FOREGROUND_RED );
763
+ DEF_SELF_CONST( FOREGROUND_INTENSITY );
764
+ DEF_SELF_CONST( BACKGROUND_BLUE );
765
+ DEF_SELF_CONST( BACKGROUND_GREEN );
766
+ DEF_SELF_CONST( BACKGROUND_RED );
767
+ DEF_SELF_CONST( BACKGROUND_INTENSITY );
768
+
769
+ DEF_SELF_CONST( ENABLE_PROCESSED_INPUT );
770
+ DEF_SELF_CONST( ENABLE_LINE_INPUT );
771
+ DEF_SELF_CONST( ENABLE_ECHO_INPUT );
772
+ DEF_SELF_CONST( ENABLE_WINDOW_INPUT );
773
+ DEF_SELF_CONST( ENABLE_MOUSE_INPUT );
774
+ DEF_SELF_CONST( ENABLE_PROCESSED_OUTPUT );
775
+ DEF_SELF_CONST( ENABLE_WRAP_AT_EOL_OUTPUT );
776
+
777
+ DEF_SELF_CONST( KEY_EVENT );
778
+ DEF_SELF_CONST( MOUSE_EVENT );
779
+ DEF_SELF_CONST( WINDOW_BUFFER_SIZE_EVENT );
780
+ DEF_SELF_CONST( MENU_EVENT );
781
+ DEF_SELF_CONST( FOCUS_EVENT );
782
+
783
+ DEF_SELF_CONST( CAPSLOCK_ON );
784
+ DEF_SELF_CONST( ENHANCED_KEY );
785
+ DEF_SELF_CONST( NUMLOCK_ON );
786
+ DEF_SELF_CONST( SHIFT_PRESSED );
787
+ DEF_SELF_CONST( LEFT_CTRL_PRESSED );
788
+ DEF_SELF_CONST( RIGHT_CTRL_PRESSED );
789
+ DEF_SELF_CONST( LEFT_ALT_PRESSED );
790
+ DEF_SELF_CONST( RIGHT_ALT_PRESSED );
791
+ DEF_SELF_CONST( SCROLLLOCK_ON );
792
+
793
+ DEF_SELF_CONST( MOUSE_WHEELED );
794
+ DEF_SELF_CONST( DOUBLE_CLICK );
795
+ DEF_SELF_CONST( MOUSE_MOVED );
796
+
797
+ DEF_SELF_CONST( FROM_LEFT_1ST_BUTTON_PRESSED );
798
+ DEF_SELF_CONST( FROM_LEFT_2ND_BUTTON_PRESSED );
799
+ DEF_SELF_CONST( FROM_LEFT_3RD_BUTTON_PRESSED );
800
+ DEF_SELF_CONST( FROM_LEFT_4TH_BUTTON_PRESSED );
801
+ DEF_SELF_CONST( RIGHTMOST_BUTTON_PRESSED );
802
+
803
+ DEF_SELF_CONST( CTRL_C_EVENT );
804
+ DEF_SELF_CONST( CTRL_BREAK_EVENT );
805
+ DEF_SELF_CONST( CTRL_CLOSE_EVENT );
806
+ DEF_SELF_CONST( CTRL_LOGOFF_EVENT );
807
+ DEF_SELF_CONST( CTRL_SHUTDOWN_EVENT );
808
+ }
809
+
810
+
811
+ VALUE
812
+ rb_FillConsoleOutputAttribute( VALUE self, VALUE hConsoleOutput,
813
+ VALUE wAttribute, VALUE nLength,
814
+ VALUE col, VALUE row )
815
+ {
816
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
817
+
818
+ COORD dwWriteCoord;
819
+ dwWriteCoord.X = NUM2UINT(col);
820
+ dwWriteCoord.Y = NUM2UINT(row);
821
+ DWORD numChars;
822
+ if (FillConsoleOutputAttribute( handle, NUM2UINT(wAttribute),
823
+ NUM2ULONG(nLength), dwWriteCoord,
824
+ &numChars ))
825
+ return ULONG2NUM(numChars);
826
+ return rb_getWin32Error();
827
+ }
828
+
829
+ VALUE
830
+ rb_SetConsoleScreenBufferSize( VALUE self, VALUE hConsoleOutput,
831
+ VALUE x, VALUE y )
832
+ {
833
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
834
+ COORD size;
835
+ size.X=NUM2UINT(x);
836
+ size.Y=NUM2UINT(y);
837
+ if (SetConsoleScreenBufferSize(handle, size))
838
+ return NUM2UINT(1);
839
+ return rb_getWin32Error();
840
+ }
841
+
842
+ VALUE
843
+ rb_SetConsoleTitle( VALUE self, VALUE title )
844
+ {
845
+ Check_Type( title, T_STRING );
846
+ if (SetConsoleTitle(RSTRING_PTR( title )))
847
+ return NUM2UINT(1);
848
+ return rb_getWin32Error();
849
+ }
850
+
851
+ VALUE
852
+ rb_SetStdHandle( VALUE self, VALUE fd, VALUE hConsoleOutput )
853
+ {
854
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
855
+ if (SetStdHandle(NUM2UINT(fd), handle))
856
+ return NUM2UINT(1);
857
+ return rb_getWin32Error();
858
+ }
859
+
860
+ VALUE
861
+ rb_SetConsoleWindowInfo( VALUE self, VALUE hConsoleOutput, VALUE bAbsolute,
862
+ VALUE left, VALUE top, VALUE right, VALUE bottom )
863
+ {
864
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
865
+
866
+ SMALL_RECT rect;
867
+ rect.Left = NUM2INT( left );
868
+ rect.Top = NUM2INT( top );
869
+ rect.Right = NUM2INT( right );
870
+ rect.Bottom = NUM2INT( bottom );
871
+ if (SetConsoleWindowInfo( handle, NUM2INT( bAbsolute ), &rect ))
872
+ return UINT2NUM(1);
873
+ return rb_getWin32Error();
874
+ }
875
+
876
+
877
+
878
+ VALUE
879
+ rb_SetConsoleCursorPosition( VALUE self, VALUE hConsoleOutput,
880
+ VALUE col, VALUE row )
881
+ {
882
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
883
+
884
+ COORD dwWriteCoord;
885
+ dwWriteCoord.X = NUM2UINT(col);
886
+ dwWriteCoord.Y = NUM2UINT(row);
887
+ // Cannot call rb_getWin32Error as this function fails when
888
+ // setting cursor to last column/row.
889
+ if ( !SetConsoleCursorPosition( handle, dwWriteCoord ) )
890
+ return Qnil;
891
+ return INT2FIX(1);
892
+ }
893
+
894
+ VALUE
895
+ rb_SetConsoleCursorInfo( VALUE self, VALUE hConsoleOutput,
896
+ VALUE size, VALUE visib )
897
+ {
898
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
899
+ CONSOLE_CURSOR_INFO c;
900
+ c.dwSize = NUM2UINT(size);
901
+ c.bVisible = NUM2UINT(visib);
902
+ if ( !SetConsoleCursorInfo( handle, &c ) )
903
+ return rb_getWin32Error();
904
+ return INT2FIX(1);
905
+ }
906
+
907
+
908
+
909
+ VALUE
910
+ rb_SetConsoleActiveScreenBuffer( VALUE self, VALUE hConsoleOutput )
911
+ {
912
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
913
+
914
+ if ( !SetConsoleActiveScreenBuffer( handle ) )
915
+ return rb_getWin32Error();
916
+ return INT2FIX(1);
917
+ }
918
+
919
+ VALUE
920
+ rb_SetConsoleTextAttribute( VALUE self, VALUE hConsoleOutput,
921
+ VALUE wAttributes )
922
+ {
923
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
924
+
925
+ if ( !SetConsoleTextAttribute( handle, NUM2UINT(wAttributes) ) )
926
+ return Qnil; // no getWin32Error to allow piping/redirecting
927
+ return INT2FIX(1);
928
+ }
929
+
930
+
931
+
932
+ VALUE
933
+ rb_ScrollConsoleScreenBuffer( VALUE self, VALUE hConsoleOutput, VALUE left1,
934
+ VALUE top1, VALUE right1, VALUE bottom1,
935
+ VALUE col, VALUE row, VALUE cChar, VALUE attr,
936
+ VALUE left2, VALUE top2, VALUE right2,
937
+ VALUE bottom2)
938
+ {
939
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
940
+
941
+ SMALL_RECT scroll, clip;
942
+ scroll.Left = NUM2INT( left1 );
943
+ scroll.Right = NUM2INT( right1 );
944
+ scroll.Top = NUM2INT( top1 );
945
+ scroll.Bottom = NUM2INT( bottom1 );
946
+ clip.Left = NUM2INT( left2 );
947
+ clip.Right = NUM2INT( right2 );
948
+ clip.Top = NUM2INT( top2 );
949
+ clip.Bottom = NUM2INT( bottom2 );
950
+ CHAR_INFO fill;
951
+ #ifdef UNICODE
952
+ fill.Char.UnicodeChar = NUM2CHR( cChar );
953
+ #else
954
+ fill.Char.AsciiChar = NUM2CHR( cChar );
955
+ #endif
956
+ fill.Attributes = NUM2INT(attr);
957
+ COORD origin;
958
+ origin.X = NUM2UINT( col );
959
+ origin.Y = NUM2UINT( row );
960
+
961
+ if ( ScrollConsoleScreenBuffer( handle, &scroll, &clip, origin,
962
+ &fill ) )
963
+ return INT2FIX(1);
964
+ return rb_getWin32Error();
965
+ }
966
+
967
+
968
+ VALUE
969
+ rb_FillConsoleOutputCharacter( VALUE self, VALUE hConsoleOutput,
970
+ VALUE cCharacter, VALUE nLength,
971
+ VALUE col, VALUE row )
972
+ {
973
+ HANDLE handle = ULongToPtr( NUM2ULONG( hConsoleOutput ) );
974
+
975
+ COORD dwWriteCoord;
976
+ dwWriteCoord.X = NUM2UINT(col);
977
+ dwWriteCoord.Y = NUM2UINT(row);
978
+ DWORD numChars;
979
+ if (FillConsoleOutputCharacter( handle, NUM2CHR(cCharacter),
980
+ NUM2ULONG(nLength), dwWriteCoord,
981
+ &numChars ))
982
+ return ULONG2NUM(numChars);
983
+ return rb_getWin32Error();
984
+ }
985
+
986
+
987
+ VALUE
988
+ rb_WriteConsoleInput(int argc, VALUE *argv, VALUE self)
989
+ {
990
+ if (argc < 3)
991
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
992
+
993
+ HANDLE handle = ULongToPtr( NUM2ULONG( argv[0] ) );
994
+ WORD type = NUM2INT( argv[1] );
995
+ DWORD written;
996
+ INPUT_RECORD event;
997
+ event.EventType = type;
998
+ switch(event.EventType) {
999
+ case KEY_EVENT:
1000
+ {
1001
+ KEY_EVENT_RECORD* kevent=(KEY_EVENT_RECORD *)&(event.Event);
1002
+ kevent->bKeyDown=(BOOL)NUM2UINT( argv[2] );
1003
+ kevent->wRepeatCount=NUM2UINT( argv[3] );
1004
+ kevent->wVirtualKeyCode=NUM2UINT( argv[4] );
1005
+ kevent->wVirtualScanCode=NUM2UINT( argv[5] );
1006
+ #ifdef UNICODE
1007
+ if (argc < 7)
1008
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1009
+ kevent->uChar.UnicodeChar=NUM2UINT( argv[6] );
1010
+ #else
1011
+ if (argc < 8)
1012
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1013
+ kevent->uChar.AsciiChar=NUM2UINT( argv[7] );
1014
+ #endif
1015
+ break;
1016
+ }
1017
+ case MOUSE_EVENT:
1018
+ {
1019
+ if (argc < 7)
1020
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1021
+
1022
+ MOUSE_EVENT_RECORD* mevent=(MOUSE_EVENT_RECORD *)&(event.Event);
1023
+ mevent->dwMousePosition.X=NUM2UINT( argv[2] );
1024
+ mevent->dwMousePosition.Y=NUM2UINT( argv[3] );
1025
+ mevent->dwButtonState=NUM2UINT( argv[4] );
1026
+ mevent->dwControlKeyState=NUM2UINT( argv[5] );
1027
+ mevent->dwEventFlags=NUM2UINT( argv[6] );
1028
+ break;
1029
+ }
1030
+ case WINDOW_BUFFER_SIZE_EVENT:
1031
+ {
1032
+ if (argc < 4)
1033
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1034
+ WINDOW_BUFFER_SIZE_RECORD* mevent=
1035
+ (WINDOW_BUFFER_SIZE_RECORD *)&(event.Event);
1036
+ mevent->dwSize.X = NUM2UINT( argv[2] );
1037
+ mevent->dwSize.Y = NUM2UINT( argv[3] );
1038
+ }
1039
+ break;
1040
+ case MENU_EVENT:
1041
+ {
1042
+ if (argc < 3)
1043
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1044
+ MENU_EVENT_RECORD* mevent= (MENU_EVENT_RECORD *)&(event.Event);
1045
+ mevent->dwCommandId = argv[2];
1046
+ }
1047
+ break;
1048
+ case FOCUS_EVENT:
1049
+ {
1050
+ if (argc < 3)
1051
+ rb_raise(rb_eArgError, "Wrong number of arguments.");
1052
+ FOCUS_EVENT_RECORD* mevent= (FOCUS_EVENT_RECORD *)&(event.Event);
1053
+ mevent->bSetFocus = NUM2UINT( argv[2] );
1054
+ }
1055
+ default:
1056
+ rb_raise( rb_eArgError, "Unknown type of event.");
1057
+ break;
1058
+ }
1059
+ if (WriteConsoleInput(handle,&event,1,&written))
1060
+ return INT2FIX(1);
1061
+ return rb_getWin32Error();
1062
+ }
1063
+
1064
+ VALUE
1065
+ rb_WriteConsoleOutput(VALUE self, VALUE h, VALUE buffer,
1066
+ VALUE srcwid, VALUE srcht, VALUE startx,
1067
+ VALUE starty, VALUE l, VALUE t, VALUE r, VALUE b)
1068
+ {
1069
+ COORD coords;
1070
+ COORD size;
1071
+ SMALL_RECT to;
1072
+
1073
+ HANDLE handle = ULongToPtr( NUM2ULONG( h ) );
1074
+ Check_Type( buffer, T_STRING );
1075
+ size.X=NUM2UINT( srcwid );
1076
+ size.Y=NUM2UINT( srcht );
1077
+ coords.X=NUM2INT( startx );
1078
+ coords.Y=NUM2INT( starty );
1079
+ to.Left = NUM2INT( l );
1080
+ to.Top = NUM2INT( t );
1081
+ to.Right = NUM2INT( r );
1082
+ to.Bottom = NUM2INT( b );
1083
+ if (WriteConsoleOutput(handle,(CHAR_INFO *)RSTRING_PTR(buffer),
1084
+ size,coords,&to)) {
1085
+ VALUE ret = rb_ary_new();
1086
+ rb_ary_push( ret, INT2FIX( to.Left ) );
1087
+ rb_ary_push( ret, INT2FIX( to.Top ) );
1088
+ rb_ary_push( ret, INT2FIX( to.Right ) );
1089
+ rb_ary_push( ret, INT2FIX( to.Bottom ) );
1090
+ return ret;
1091
+ }
1092
+ return rb_getWin32Error();
1093
+ }
1094
+
1095
+
1096
+ VALUE
1097
+ rb_WriteConsoleOutputAttribute(VALUE self, VALUE h, VALUE s,
1098
+ VALUE x, VALUE y)
1099
+ {
1100
+
1101
+ HANDLE handle = ULongToPtr( NUM2ULONG( h ) );
1102
+ Check_Type( s, T_STRING );
1103
+
1104
+ unsigned short buffer[80*999*sizeof(unsigned short)];
1105
+ DWORD written;
1106
+ DWORD towrite = RSTRING_LEN(s);
1107
+ unsigned i = 0;
1108
+
1109
+ for(i=0; i<towrite; i++) {
1110
+ buffer[i] = (unsigned short)(RSTRING_PTR(s)[i]);
1111
+ }
1112
+ COORD coords;
1113
+ coords.X=NUM2INT( x );
1114
+ coords.Y=NUM2INT( y );
1115
+ if (WriteConsoleOutputAttribute(handle,(const unsigned short *)&buffer,
1116
+ towrite,coords,&written)) {
1117
+ return UINT2NUM( written );
1118
+ }
1119
+ return rb_getWin32Error();
1120
+ }
1121
+
1122
+
1123
+ VALUE
1124
+ rb_WriteConsoleOutputCharacter(VALUE self, VALUE h, VALUE s,
1125
+ VALUE x, VALUE y)
1126
+ {
1127
+
1128
+ HANDLE handle = ULongToPtr( NUM2ULONG( h ) );
1129
+ Check_Type( s, T_STRING );
1130
+
1131
+ DWORD written;
1132
+ COORD coords;
1133
+ coords.X=NUM2INT( x );
1134
+ coords.Y=NUM2INT( y );
1135
+ if (WriteConsoleOutputCharacter(handle,(LPCTSTR)RSTRING_PTR(s),
1136
+ RSTRING_LEN(s),coords,&written)) {
1137
+ return UINT2NUM( written );
1138
+ }
1139
+ return rb_getWin32Error();
1140
+ }
1141
+
1142
+
1143
+ void Init_Console_ext(void)
1144
+ {
1145
+ rb_mWin32 = rb_define_module("Win32");
1146
+ rb_define_const(rb_mKernel, "Win32", rb_mWin32);
1147
+
1148
+ rb_mConsole = rb_define_class_under(rb_mWin32, "Console", rb_cObject);
1149
+
1150
+ // Handle Constants
1151
+ rb_mConstants = rb_define_module_under(rb_mConsole,"Constants");
1152
+ define_constants();
1153
+
1154
+ // Handle API
1155
+ rb_mAPI = rb_define_class_under(rb_mConsole, "API", rb_cObject);
1156
+
1157
+ RB_DEF_API_METHOD(constant, 1); //OK
1158
+
1159
+ RB_DEF_API_METHOD(AllocConsole, 0);
1160
+
1161
+ RB_DEF_API_METHOD(CreateConsoleScreenBuffer, 3); //OK
1162
+
1163
+ RB_DEF_API_METHOD(FillConsoleOutputAttribute, 5); //OK
1164
+ RB_DEF_API_METHOD(FillConsoleOutputCharacter, 5); //OK
1165
+ // RB_DEF_API_METHOD(FillConsoleInputBuffer, 1); // Does not exist anymore
1166
+
1167
+ RB_DEF_API_METHOD(FreeConsole, 0);
1168
+
1169
+ RB_DEF_API_METHOD(GenerateConsoleCtrlEvent, 2);
1170
+
1171
+ RB_DEF_API_METHOD(GetConsoleCP, 0); //OK
1172
+ RB_DEF_API_METHOD(GetConsoleCursorInfo, 1); //OK
1173
+ RB_DEF_API_METHOD(GetConsoleMode, 1);
1174
+ RB_DEF_API_METHOD(GetConsoleOutputCP, 0);
1175
+ RB_DEF_API_METHOD(GetConsoleScreenBufferInfo, 1); //OK
1176
+ RB_DEF_API_METHOD(GetConsoleTitle, 0);
1177
+ RB_DEF_API_METHOD(GetConsoleWindow, 0);
1178
+ RB_DEF_API_METHOD(GetLargestConsoleWindowSize, 1);
1179
+ RB_DEF_API_METHOD(GetNumberOfConsoleInputEvents, 1);
1180
+ RB_DEF_API_METHOD(GetNumberOfConsoleMouseButtons, 0);
1181
+
1182
+ RB_DEF_API_METHOD(GetStdHandle, 1); //OK
1183
+
1184
+ RB_DEF_API_METHOD(PeekConsoleInput, 1); //OK
1185
+ RB_DEF_API_METHOD(ReadConsole, 3); //OK
1186
+ RB_DEF_API_METHOD(ReadConsoleInput, 1); //OK
1187
+
1188
+ RB_DEF_API_METHOD(ReadConsoleOutput, 10); // OK
1189
+ RB_DEF_API_METHOD(ReadConsoleOutputAttribute, 4); // OK
1190
+ RB_DEF_API_METHOD(ReadConsoleOutputCharacter, 5); // OK
1191
+
1192
+
1193
+ RB_DEF_API_METHOD(ScrollConsoleScreenBuffer, 13); //OK
1194
+
1195
+ RB_DEF_API_METHOD(SetConsoleActiveScreenBuffer, 1);
1196
+ RB_DEF_API_METHOD(SetConsoleCP, 1);
1197
+ RB_DEF_API_METHOD(SetConsoleCursorPosition, 3);
1198
+ RB_DEF_API_METHOD(SetConsoleCursorInfo, 3);
1199
+ RB_DEF_API_METHOD(SetConsoleMode, 2); //OK
1200
+ RB_DEF_API_METHOD(SetConsoleOutputCP, 1);
1201
+ RB_DEF_API_METHOD(SetConsoleScreenBufferSize, 3);
1202
+ RB_DEF_API_METHOD(SetConsoleTextAttribute, 2);
1203
+ RB_DEF_API_METHOD(SetConsoleTitle, 1); //OK
1204
+ RB_DEF_API_METHOD(SetConsoleWindowInfo, 6);
1205
+
1206
+ RB_DEF_API_METHOD(SetStdHandle, 2);
1207
+
1208
+ RB_DEF_API_METHOD(WriteConsole, 2);
1209
+ RB_DEF_API_METHOD(WriteFile, 2);
1210
+
1211
+ RB_DEF_API_METHOD(WriteConsoleInput, -1);
1212
+ RB_DEF_API_METHOD(WriteConsoleOutput, 10);
1213
+ RB_DEF_API_METHOD(WriteConsoleOutputAttribute, 4);
1214
+ RB_DEF_API_METHOD(WriteConsoleOutputCharacter, 4);
1215
+
1216
+ }