зеркало из https://github.com/github/ruby.git
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:
Родитель
4d9de3db0a
Коммит
43b00d8a11
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче