mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
win32.c: manage reverse video
* win32/win32.c (constat_attr): manage reverse video internally since Windows console window does not manage it. based on the patch by white leaf in [ruby-dev:48483]. [Bug #10158] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47241 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
4d9de3db0a
commit
43b00d8a11
7 changed files with 137 additions and 14 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
Thu Aug 21 17:10:31 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* win32/win32.c (constat_attr): manage reverse video internally
|
||||||
|
since Windows console window does not manage it. based on the
|
||||||
|
patch by white leaf in [ruby-dev:48483]. [Bug #10158]
|
||||||
|
|
||||||
Thu Aug 21 14:45:41 2014 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
|
Thu Aug 21 14:45:41 2014 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
|
||||||
|
|
||||||
* lib/e2mmap.rb: removed commented-out code.
|
* lib/e2mmap.rb: removed commented-out code.
|
||||||
|
|
44
ext/-test-/win32/console/attribute.c
Normal file
44
ext/-test-/win32/console/attribute.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
static VALUE rb_cConsoleScreenBufferInfo;
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
console_info(VALUE io)
|
||||||
|
{
|
||||||
|
int fd = NUM2INT(rb_funcallv(io, rb_intern("fileno"), 0, 0));
|
||||||
|
HANDLE h = (HANDLE)rb_w32_get_osfhandle(fd);
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
|
||||||
|
if (h == (HANDLE)-1) rb_raise(rb_eIOError, "invalid io");
|
||||||
|
if (!GetConsoleScreenBufferInfo(h, &csbi))
|
||||||
|
rb_syserr_fail(rb_w32_map_errno(GetLastError()), "not console");
|
||||||
|
return rb_struct_new(rb_cConsoleScreenBufferInfo,
|
||||||
|
INT2FIX(csbi.dwSize.X), INT2FIX(csbi.dwSize.Y),
|
||||||
|
INT2FIX(csbi.dwCursorPosition.X), INT2FIX(csbi.dwCursorPosition.Y),
|
||||||
|
INT2FIX(csbi.wAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
|
||||||
|
#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_attribute(VALUE m)
|
||||||
|
{
|
||||||
|
rb_cConsoleScreenBufferInfo = rb_struct_define_under(m, "ConsoleScreenBufferInfo",
|
||||||
|
"size_x", "size_y",
|
||||||
|
"cur_x", "cur_y",
|
||||||
|
"attr", NULL);
|
||||||
|
rb_define_method(rb_cIO, "console_info", console_info, 0);
|
||||||
|
|
||||||
|
rb_define_const(m, "FOREGROUND_MASK", INT2FIX(FOREGROUND_MASK));
|
||||||
|
rb_define_const(m, "FOREGROUND_BLUE", INT2FIX(FOREGROUND_BLUE));
|
||||||
|
rb_define_const(m, "FOREGROUND_GREEN", INT2FIX(FOREGROUND_GREEN));
|
||||||
|
rb_define_const(m, "FOREGROUND_RED", INT2FIX(FOREGROUND_RED));
|
||||||
|
rb_define_const(m, "FOREGROUND_INTENSITY", INT2FIX(FOREGROUND_INTENSITY));
|
||||||
|
|
||||||
|
rb_define_const(m, "BACKGROUND_MASK", INT2FIX(BACKGROUND_MASK));
|
||||||
|
rb_define_const(m, "BACKGROUND_BLUE", INT2FIX(BACKGROUND_BLUE));
|
||||||
|
rb_define_const(m, "BACKGROUND_GREEN", INT2FIX(BACKGROUND_GREEN));
|
||||||
|
rb_define_const(m, "BACKGROUND_RED", INT2FIX(BACKGROUND_RED));
|
||||||
|
rb_define_const(m, "BACKGROUND_INTENSITY", INT2FIX(BACKGROUND_INTENSITY));
|
||||||
|
}
|
1
ext/-test-/win32/console/depend
Normal file
1
ext/-test-/win32/console/depend
Normal file
|
@ -0,0 +1 @@
|
||||||
|
attribute.o: $(ruby_headers) $(hdrdir)/ruby/win32.h
|
8
ext/-test-/win32/console/extconf.rb
Normal file
8
ext/-test-/win32/console/extconf.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
if $mingw or $mswin
|
||||||
|
$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
|
||||||
|
inits = $srcs.map {|s| File.basename(s, ".*")}
|
||||||
|
inits.delete("init")
|
||||||
|
inits.map! {|s|"X(#{s})"}
|
||||||
|
$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
|
||||||
|
create_makefile("-test-/win32/console")
|
||||||
|
end
|
11
ext/-test-/win32/console/init.c
Normal file
11
ext/-test-/win32/console/init.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "ruby.h"
|
||||||
|
|
||||||
|
#define init(n) {void Init_##n(VALUE m); Init_##n(m);}
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_console(void)
|
||||||
|
{
|
||||||
|
VALUE mBug = rb_define_module("Bug");
|
||||||
|
VALUE m = rb_define_module_under(mBug, "Win32");
|
||||||
|
TEST_INIT_FUNCS(init);
|
||||||
|
}
|
44
test/-ext-/win32/test_console_attr.rb
Normal file
44
test/-ext-/win32/test_console_attr.rb
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
if /mswin|mingw/ =~ RUBY_PLATFORM and STDOUT.tty?
|
||||||
|
require '-test-/win32/console'
|
||||||
|
require 'io/console'
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
class Test_Win32Console < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
print "\e[m!"
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
print "\e[m!"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_default
|
||||||
|
info = STDOUT.console_info
|
||||||
|
assert_equal(7, info.attr);
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_reverse
|
||||||
|
print "\e[7m"
|
||||||
|
info = STDOUT.console_info
|
||||||
|
assert_equal(0x70, info.attr);
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_bold
|
||||||
|
print "\e[1m"
|
||||||
|
info = STDOUT.console_info
|
||||||
|
assert_equal(0x8, info.attr&0x8);
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_bold_reverse
|
||||||
|
print "\e[1;7m"
|
||||||
|
info = STDOUT.console_info
|
||||||
|
assert_equal(0xf0, info.attr);
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_reverse_bold
|
||||||
|
print "\e[7;1m"
|
||||||
|
info = STDOUT.console_info
|
||||||
|
assert_equal(0xf0, info.attr);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -615,7 +615,7 @@ static char *uenvarea;
|
||||||
/* License: Ruby's */
|
/* License: Ruby's */
|
||||||
struct constat {
|
struct constat {
|
||||||
struct {
|
struct {
|
||||||
int state, seq[16];
|
int state, seq[16], reverse;
|
||||||
WORD attr;
|
WORD attr;
|
||||||
COORD saved;
|
COORD saved;
|
||||||
} vt100;
|
} vt100;
|
||||||
|
@ -5901,6 +5901,7 @@ constat_handle(HANDLE h)
|
||||||
p = ALLOC(struct constat);
|
p = ALLOC(struct constat);
|
||||||
p->vt100.state = constat_init;
|
p->vt100.state = constat_init;
|
||||||
p->vt100.attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
p->vt100.attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||||||
|
p->vt100.reverse = 0;
|
||||||
p->vt100.saved.X = p->vt100.saved.Y = 0;
|
p->vt100.saved.X = p->vt100.saved.Y = 0;
|
||||||
if (GetConsoleScreenBufferInfo(h, &csbi)) {
|
if (GetConsoleScreenBufferInfo(h, &csbi)) {
|
||||||
p->vt100.attr = csbi.wAttributes;
|
p->vt100.attr = csbi.wAttributes;
|
||||||
|
@ -5922,16 +5923,26 @@ constat_reset(HANDLE h)
|
||||||
p->vt100.state = constat_init;
|
p->vt100.state = constat_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
|
||||||
|
#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
|
||||||
|
|
||||||
|
#define constat_attr_color_reverse(attr) \
|
||||||
|
(attr) & ~(FOREGROUND_MASK | BACKGROUND_MASK) | \
|
||||||
|
(((attr) & FOREGROUND_MASK) << 4) | \
|
||||||
|
(((attr) & BACKGROUND_MASK) >> 4);
|
||||||
|
|
||||||
/* License: Ruby's */
|
/* License: Ruby's */
|
||||||
static WORD
|
static WORD
|
||||||
constat_attr(int count, const int *seq, WORD attr, WORD default_attr)
|
constat_attr(int count, const int *seq, WORD attr, WORD default_attr, int *reverse)
|
||||||
{
|
{
|
||||||
#define FOREGROUND_MASK (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
|
int rev = *reverse;
|
||||||
#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED)
|
WORD bold;
|
||||||
WORD bold = attr & (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
|
|
||||||
int rev = 0;
|
|
||||||
|
|
||||||
if (!count) return attr;
|
if (!count) return attr;
|
||||||
|
if (rev) attr = constat_attr_color_reverse(attr);
|
||||||
|
bold = attr & FOREGROUND_INTENSITY;
|
||||||
|
attr &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
|
||||||
|
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
switch (*seq++) {
|
switch (*seq++) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -5940,7 +5951,7 @@ constat_attr(int count, const int *seq, WORD attr, WORD default_attr)
|
||||||
bold = 0;
|
bold = 0;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
bold |= rev ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
|
bold = FOREGROUND_INTENSITY;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
#ifndef COMMON_LVB_UNDERSCORE
|
#ifndef COMMON_LVB_UNDERSCORE
|
||||||
|
@ -6010,12 +6021,10 @@ constat_attr(int count, const int *seq, WORD attr, WORD default_attr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rev) {
|
attr |= bold;
|
||||||
attr = attr & ~(FOREGROUND_MASK | BACKGROUND_MASK) |
|
if (rev) attr = constat_attr_color_reverse(attr);
|
||||||
((attr & FOREGROUND_MASK) << 4) |
|
*reverse = rev;
|
||||||
((attr & BACKGROUND_MASK) >> 4);
|
return attr;
|
||||||
}
|
|
||||||
return attr | bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* License: Ruby's */
|
/* License: Ruby's */
|
||||||
|
@ -6033,7 +6042,7 @@ constat_apply(HANDLE handle, struct constat *s, WCHAR w)
|
||||||
if (count > 0 && seq[0] > 0) arg1 = seq[0];
|
if (count > 0 && seq[0] > 0) arg1 = seq[0];
|
||||||
switch (w) {
|
switch (w) {
|
||||||
case L'm':
|
case L'm':
|
||||||
SetConsoleTextAttribute(handle, constat_attr(count, seq, csbi.wAttributes, s->vt100.attr));
|
SetConsoleTextAttribute(handle, constat_attr(count, seq, csbi.wAttributes, s->vt100.attr, &s->vt100.reverse));
|
||||||
break;
|
break;
|
||||||
case L'F':
|
case L'F':
|
||||||
csbi.dwCursorPosition.X = 0;
|
csbi.dwCursorPosition.X = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue