Feature #6418 » ansi_escape2.diff
win32/win32.c (working copy) | ||
---|---|---|
HANDLE handle;
|
||
DWORD dwMode, reslen;
|
||
VALUE str = strarg;
|
||
rb_encoding *utf16 = rb_enc_find("UTF-16LE");
|
||
char *ptr;
|
||
long len;
|
||
static WORD attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||
if (disable) return -1L;
|
||
handle = (HANDLE)_osfhnd(fd);
|
||
... | ... | |
!rb_econv_has_convpath_p(rb_enc_name(rb_enc_get(str)), "UTF-16LE"))
|
||
return -1L;
|
||
str = rb_str_encode(str, rb_enc_from_encoding(rb_enc_find("UTF-16LE")),
|
||
str = rb_str_encode(str, rb_enc_from_encoding(utf16),
|
||
ECONV_INVALID_REPLACE|ECONV_UNDEF_REPLACE, Qnil);
|
||
if (!WriteConsoleW(handle, (LPWSTR)RSTRING_PTR(str), RSTRING_LEN(str)/2,
|
||
&reslen, NULL)) {
|
||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||
disable = TRUE;
|
||
return -1L;
|
||
ptr = RSTRING_PTR(str);
|
||
len = RSTRING_LEN(str);
|
||
while (len > 0) {
|
||
long pos = rb_memsearch(L"\x1B[", 4, ptr, len, utf16);
|
||
long curlen = pos < 0 ? len : pos;
|
||
if (curlen > 0) {
|
||
if (!WriteConsoleW(handle, (LPWSTR)ptr, curlen/2, &reslen, NULL)) {
|
||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||
disable = TRUE;
|
||
return -1L;
|
||
}
|
||
ptr += curlen;
|
||
len -= curlen;
|
||
}
|
||
if (pos >= 0) {
|
||
int seq = -1;
|
||
int rev = 0;
|
||
ptr += 4;
|
||
len -= 4;
|
||
while (len > 1) {
|
||
WCHAR w = *(LPWSTR)ptr;
|
||
if (w == L';' || w == L'm') {
|
||
ptr += 2;
|
||
len -= 2;
|
||
switch (seq) {
|
||
case 0:
|
||
attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||
rev = 0;
|
||
break;
|
||
case 4:
|
||
#ifndef COMMON_LVB_UNDERSCORE
|
||
#define COMMON_LVB_UNDERSCORE 0x8000
|
||
#endif
|
||
attr |= COMMON_LVB_UNDERSCORE;
|
||
break;
|
||
case 7:
|
||
rev = 1;
|
||
break;
|
||
case 30:
|
||
attr &= ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||
case 17:
|
||
case 31:
|
||
attr = attr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN) | FOREGROUND_RED;
|
||
break;
|
||
case 18:
|
||
case 32:
|
||
attr = attr & ~(FOREGROUND_BLUE | FOREGROUND_RED) | FOREGROUND_GREEN;
|
||
break;
|
||
case 19:
|
||
case 33:
|
||
attr = attr & ~FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||
break;
|
||
case 20:
|
||
case 34:
|
||
attr = attr & ~(FOREGROUND_GREEN | FOREGROUND_RED) | FOREGROUND_BLUE;
|
||
break;
|
||
case 21:
|
||
case 35:
|
||
attr = attr & ~FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
|
||
break;
|
||
case 22:
|
||
case 36:
|
||
attr = attr & ~FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
|
||
break;
|
||
case 23:
|
||
case 37:
|
||
attr |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
||
break;
|
||
case 40:
|
||
attr &= ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
|
||
case 41:
|
||
attr = attr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN) | BACKGROUND_RED;
|
||
break;
|
||
case 42:
|
||
attr = attr & ~(BACKGROUND_BLUE | BACKGROUND_RED) | BACKGROUND_GREEN;
|
||
break;
|
||
case 43:
|
||
attr = attr & ~BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
|
||
break;
|
||
case 44:
|
||
attr = attr & ~(BACKGROUND_GREEN | BACKGROUND_RED) | BACKGROUND_BLUE;
|
||
break;
|
||
case 45:
|
||
attr = attr & ~BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
|
||
break;
|
||
case 46:
|
||
attr = attr & ~BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
|
||
break;
|
||
case 47:
|
||
attr |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
|
||
break;
|
||
}
|
||
if (rev) {
|
||
WORD attr2 = attr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED) | ((attr & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)) << 4) | ((attr & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED)) >> 4);
|
||
SetConsoleTextAttribute(handle, attr2);
|
||
}
|
||
else {
|
||
SetConsoleTextAttribute(handle, attr);
|
||
}
|
||
if (w == L'm') {
|
||
break;
|
||
}
|
||
seq = -1;
|
||
}
|
||
else if (w == L'A') {
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
ptr += 2;
|
||
len -= 2;
|
||
if (GetConsoleScreenBufferInfo(handle, &csbi)) {
|
||
csbi.dwCursorPosition.Y -= (seq < 0 ? 1 : seq);
|
||
if (csbi.dwCursorPosition.Y >= 0) {
|
||
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
|
||
}
|
||
}
|
||
seq = -1;
|
||
}
|
||
else if (w == L'B') {
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
ptr += 2;
|
||
len -= 2;
|
||
if (GetConsoleScreenBufferInfo(handle, &csbi)) {
|
||
csbi.dwCursorPosition.Y += (seq < 0 ? 1 : seq);
|
||
if (csbi.dwCursorPosition.Y < csbi.dwSize.Y) {
|
||
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
|
||
}
|
||
}
|
||
seq = -1;
|
||
}
|
||
else if (w == L'C') {
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
ptr += 2;
|
||
len -= 2;
|
||
if (GetConsoleScreenBufferInfo(handle, &csbi)) {
|
||
csbi.dwCursorPosition.X += (seq < 0 ? 1 : seq);
|
||
if (csbi.dwCursorPosition.X < csbi.dwSize.X) {
|
||
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
|
||
}
|
||
}
|
||
seq = -1;
|
||
}
|
||
else if (w == L'D') {
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
ptr += 2;
|
||
len -= 2;
|
||
if (GetConsoleScreenBufferInfo(handle, &csbi)) {
|
||
csbi.dwCursorPosition.X -= (seq < 0 ? 1 : seq);
|
||
if (csbi.dwCursorPosition.X >= 0) {
|
||
SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
|
||
}
|
||
}
|
||
seq = -1;
|
||
}
|
||
else if (w == L'K') {
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
COORD pos;
|
||
DWORD written;
|
||
ptr += 2;
|
||
len -= 2;
|
||
if (GetConsoleScreenBufferInfo(handle, &csbi)) {
|
||
switch (seq) {
|
||
case 0: /* erase after cursor */
|
||
case -1:
|
||
FillConsoleOutputCharacterW(handle, L' ', csbi.dwSize.X - csbi.dwCursorPosition.X, csbi.dwCursorPosition, &written);
|
||
break;
|
||
case 1: /* erase before cursor */
|
||
pos.X = 0;
|
||
pos.Y = csbi.dwCursorPosition.Y;
|
||
FillConsoleOutputCharacterW(handle, L' ', csbi.dwCursorPosition.X, pos, &written);
|
||
break;
|
||
case 2: /* erase entire line */
|
||
pos.X = 0;
|
||
pos.Y = csbi.dwCursorPosition.Y;
|
||
FillConsoleOutputCharacterW(handle, L' ', csbi.dwSize.X, pos, &written);
|
||
break;
|
||
}
|
||
}
|
||
seq = -1;
|
||
break;
|
||
}
|
||
else if (w >= L'0' && w <= L'9') {
|
||
ptr += 2;
|
||
len -= 2;
|
||
seq = (seq < 0 ? 0 : seq * 10) + w - L'0';
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
RB_GC_GUARD(str);
|
||
return (long)reslen;
|
||
}
|
||