Project

General

Profile

Feature #6418 ยป ansi_escape2.diff

usa (Usaku NAKAMURA), 05/09/2012 06:29 PM

View differences:

win32/win32.c (working copy)
5847 5848
    HANDLE handle;
5848 5849
    DWORD dwMode, reslen;
5849 5850
    VALUE str = strarg;
5851
    rb_encoding *utf16 = rb_enc_find("UTF-16LE");
5852
    char *ptr;
5853
    long len;
5854
    static WORD attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
5850 5855

  
5851 5856
    if (disable) return -1L;
5852 5857
    handle = (HANDLE)_osfhnd(fd);
......
5854 5859
	!rb_econv_has_convpath_p(rb_enc_name(rb_enc_get(str)), "UTF-16LE"))
5855 5860
	return -1L;
5856 5861

  
5857
    str = rb_str_encode(str, rb_enc_from_encoding(rb_enc_find("UTF-16LE")),
5862
    str = rb_str_encode(str, rb_enc_from_encoding(utf16),
5858 5863
			ECONV_INVALID_REPLACE|ECONV_UNDEF_REPLACE, Qnil);
5859
    if (!WriteConsoleW(handle, (LPWSTR)RSTRING_PTR(str), RSTRING_LEN(str)/2,
5860
		       &reslen, NULL)) {
5861
	if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5862
	    disable = TRUE;
5863
	return -1L;
5864
    ptr = RSTRING_PTR(str);
5865
    len = RSTRING_LEN(str);
5866
    while (len > 0) {
5867
	long pos = rb_memsearch(L"\x1B[", 4, ptr, len, utf16);
5868
	long curlen = pos < 0 ? len : pos;
5869
	if (curlen > 0) {
5870
	    if (!WriteConsoleW(handle, (LPWSTR)ptr, curlen/2, &reslen, NULL)) {
5871
		if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5872
		    disable = TRUE;
5873
		return -1L;
5874
	    }
5875
	    ptr += curlen;
5876
	    len -= curlen;
5877
	}
5878
	if (pos >= 0) {
5879
	    int seq = -1;
5880
	    int rev = 0;
5881
	    ptr += 4;
5882
	    len -= 4;
5883
	    while (len > 1) {
5884
		WCHAR w = *(LPWSTR)ptr;
5885
		if (w == L';' || w == L'm') {
5886
		    ptr += 2;
5887
		    len -= 2;
5888
		    switch (seq) {
5889
		      case 0:
5890
			attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
5891
			rev = 0;
5892
			break;
5893
		      case 4:
5894
#ifndef COMMON_LVB_UNDERSCORE
5895
#define COMMON_LVB_UNDERSCORE 0x8000
5896
#endif
5897
			attr |= COMMON_LVB_UNDERSCORE;
5898
			break;
5899
		      case 7:
5900
			rev = 1;
5901
			break;
5902

  
5903
		      case 30:
5904
			attr &= ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
5905
		      case 17:
5906
		      case 31:
5907
			attr = attr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN) | FOREGROUND_RED;
5908
			break;
5909
		      case 18:
5910
		      case 32:
5911
			attr = attr & ~(FOREGROUND_BLUE | FOREGROUND_RED) | FOREGROUND_GREEN;
5912
			break;
5913
		      case 19:
5914
		      case 33:
5915
			attr = attr & ~FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
5916
			break;
5917
		      case 20:
5918
		      case 34:
5919
			attr = attr & ~(FOREGROUND_GREEN | FOREGROUND_RED) | FOREGROUND_BLUE;
5920
			break;
5921
		      case 21:
5922
		      case 35:
5923
			attr = attr & ~FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED;
5924
			break;
5925
		      case 22:
5926
		      case 36:
5927
			attr = attr & ~FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
5928
			break;
5929
		      case 23:
5930
		      case 37:
5931
			attr |= FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
5932
			break;
5933

  
5934
		      case 40:
5935
			attr &= ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
5936
		      case 41:
5937
			attr = attr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN) | BACKGROUND_RED;
5938
			break;
5939
		      case 42:
5940
			attr = attr & ~(BACKGROUND_BLUE | BACKGROUND_RED) | BACKGROUND_GREEN;
5941
			break;
5942
		      case 43:
5943
			attr = attr & ~BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
5944
			break;
5945
		      case 44:
5946
			attr = attr & ~(BACKGROUND_GREEN | BACKGROUND_RED) | BACKGROUND_BLUE;
5947
			break;
5948
		      case 45:
5949
			attr = attr & ~BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED;
5950
			break;
5951
		      case 46:
5952
			attr = attr & ~BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
5953
			break;
5954
		      case 47:
5955
			attr |= BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
5956
			break;
5957
		    }
5958
		    if (rev) {
5959
			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);
5960
			SetConsoleTextAttribute(handle, attr2);
5961
		    }
5962
		    else {
5963
			SetConsoleTextAttribute(handle, attr);
5964
		    }
5965
		    if (w == L'm') {
5966
			break;
5967
		    }
5968
		    seq = -1;
5969
		}
5970
		else if (w == L'A') {
5971
		    CONSOLE_SCREEN_BUFFER_INFO csbi;
5972
		    ptr += 2;
5973
		    len -= 2;
5974
		    if (GetConsoleScreenBufferInfo(handle, &csbi)) {
5975
			csbi.dwCursorPosition.Y -= (seq < 0 ? 1 : seq);
5976
			if (csbi.dwCursorPosition.Y >= 0) {
5977
			    SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
5978
			}
5979
		    }
5980
		    seq = -1;
5981
		}
5982
		else if (w == L'B') {
5983
		    CONSOLE_SCREEN_BUFFER_INFO csbi;
5984
		    ptr += 2;
5985
		    len -= 2;
5986
		    if (GetConsoleScreenBufferInfo(handle, &csbi)) {
5987
			csbi.dwCursorPosition.Y += (seq < 0 ? 1 : seq);
5988
			if (csbi.dwCursorPosition.Y < csbi.dwSize.Y) {
5989
			    SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
5990
			}
5991
		    }
5992
		    seq = -1;
5993
		}
5994
		else if (w == L'C') {
5995
		    CONSOLE_SCREEN_BUFFER_INFO csbi;
5996
		    ptr += 2;
5997
		    len -= 2;
5998
		    if (GetConsoleScreenBufferInfo(handle, &csbi)) {
5999
			csbi.dwCursorPosition.X += (seq < 0 ? 1 : seq);
6000
			if (csbi.dwCursorPosition.X < csbi.dwSize.X) {
6001
			    SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6002
			}
6003
		    }
6004
		    seq = -1;
6005
		}
6006
		else if (w == L'D') {
6007
		    CONSOLE_SCREEN_BUFFER_INFO csbi;
6008
		    ptr += 2;
6009
		    len -= 2;
6010
		    if (GetConsoleScreenBufferInfo(handle, &csbi)) {
6011
			csbi.dwCursorPosition.X -= (seq < 0 ? 1 : seq);
6012
			if (csbi.dwCursorPosition.X >= 0) {
6013
			    SetConsoleCursorPosition(handle, csbi.dwCursorPosition);
6014
			}
6015
		    }
6016
		    seq = -1;
6017
		}
6018
		else if (w == L'K') {
6019
		    CONSOLE_SCREEN_BUFFER_INFO csbi;
6020
		    COORD pos;
6021
		    DWORD written;
6022
		    ptr += 2;
6023
		    len -= 2;
6024
		    if (GetConsoleScreenBufferInfo(handle, &csbi)) {
6025
			switch (seq) {
6026
			  case 0:	/* erase after cursor */
6027
			  case -1:
6028
			    FillConsoleOutputCharacterW(handle, L' ', csbi.dwSize.X - csbi.dwCursorPosition.X, csbi.dwCursorPosition, &written);
6029
			    break;
6030
			  case 1:	/* erase before cursor */
6031
			    pos.X = 0;
6032
			    pos.Y = csbi.dwCursorPosition.Y;
6033
			    FillConsoleOutputCharacterW(handle, L' ', csbi.dwCursorPosition.X, pos, &written);
6034
			    break;
6035
			  case 2:	/* erase entire line */
6036
			    pos.X = 0;
6037
			    pos.Y = csbi.dwCursorPosition.Y;
6038
			    FillConsoleOutputCharacterW(handle, L' ', csbi.dwSize.X, pos, &written);
6039
			    break;
6040
			}
6041
		    }
6042
		    seq = -1;
6043
		    break;
6044
		}
6045
		else if (w >= L'0' && w <= L'9') {
6046
		    ptr += 2;
6047
		    len -= 2;
6048
		    seq = (seq < 0 ? 0 : seq * 10) + w - L'0';
6049
		}
6050
		else {
6051
		    break;
6052
		}
6053
	    }
6054
	}
5864 6055
    }
6056
    RB_GC_GUARD(str);
5865 6057
    return (long)reslen;
5866 6058
}
5867 6059