* 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:
nobu 2014-08-21 08:10:34 +00:00
Родитель 4d9de3db0a
Коммит 43b00d8a11
7 изменённых файлов: 137 добавлений и 14 удалений

Просмотреть файл

@ -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>
* lib/e2mmap.rb: removed commented-out code.

Просмотреть файл

@ -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));
}

Просмотреть файл

@ -0,0 +1 @@
attribute.o: $(ruby_headers) $(hdrdir)/ruby/win32.h

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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 */
struct constat {
struct {
int state, seq[16];
int state, seq[16], reverse;
WORD attr;
COORD saved;
} vt100;
@ -5901,6 +5901,7 @@ constat_handle(HANDLE h)
p = ALLOC(struct constat);
p->vt100.state = constat_init;
p->vt100.attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
p->vt100.reverse = 0;
p->vt100.saved.X = p->vt100.saved.Y = 0;
if (GetConsoleScreenBufferInfo(h, &csbi)) {
p->vt100.attr = csbi.wAttributes;
@ -5922,16 +5923,26 @@ constat_reset(HANDLE h)
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 */
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)
#define BACKGROUND_MASK (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED)
WORD bold = attr & (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
int rev = 0;
int rev = *reverse;
WORD bold;
if (!count) return attr;
if (rev) attr = constat_attr_color_reverse(attr);
bold = attr & FOREGROUND_INTENSITY;
attr &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
while (count-- > 0) {
switch (*seq++) {
case 0:
@ -5940,7 +5951,7 @@ constat_attr(int count, const int *seq, WORD attr, WORD default_attr)
bold = 0;
break;
case 1:
bold |= rev ? BACKGROUND_INTENSITY : FOREGROUND_INTENSITY;
bold = FOREGROUND_INTENSITY;
break;
case 4:
#ifndef COMMON_LVB_UNDERSCORE
@ -6010,12 +6021,10 @@ constat_attr(int count, const int *seq, WORD attr, WORD default_attr)
break;
}
}
if (rev) {
attr = attr & ~(FOREGROUND_MASK | BACKGROUND_MASK) |
((attr & FOREGROUND_MASK) << 4) |
((attr & BACKGROUND_MASK) >> 4);
}
return attr | bold;
attr |= bold;
if (rev) attr = constat_attr_color_reverse(attr);
*reverse = rev;
return attr;
}
/* 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];
switch (w) {
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;
case L'F':
csbi.dwCursorPosition.X = 0;