You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

windows.cxx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #ifdef _WIN32
  2. #include <iostream>
  3. #include "windows.hxx"
  4. #include "conversion.hxx"
  5. #include "io.hxx"
  6. #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
  7. static DWORD const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
  8. #endif
  9. using namespace std;
  10. namespace replxx {
  11. WinAttributes WIN_ATTR;
  12. template<typename T>
  13. T* HandleEsc(T* p, T* end) {
  14. if (*p == '[') {
  15. int code = 0;
  16. int thisBackground( WIN_ATTR._defaultBackground );
  17. for (++p; p < end; ++p) {
  18. char32_t c = *p;
  19. if ('0' <= c && c <= '9') {
  20. code = code * 10 + (c - '0');
  21. } else if (c == 'm' || c == ';') {
  22. switch (code) {
  23. case 0:
  24. WIN_ATTR._consoleAttribute = WIN_ATTR._defaultAttribute;
  25. WIN_ATTR._consoleColor = WIN_ATTR._defaultColor | thisBackground;
  26. break;
  27. case 1: // BOLD
  28. case 5: // BLINK
  29. WIN_ATTR._consoleAttribute = (WIN_ATTR._defaultAttribute ^ FOREGROUND_INTENSITY) & INTENSITY;
  30. break;
  31. case 22:
  32. WIN_ATTR._consoleAttribute = WIN_ATTR._defaultAttribute;
  33. break;
  34. case 30:
  35. case 90:
  36. WIN_ATTR._consoleColor = thisBackground;
  37. break;
  38. case 31:
  39. case 91:
  40. WIN_ATTR._consoleColor = FOREGROUND_RED | thisBackground;
  41. break;
  42. case 32:
  43. case 92:
  44. WIN_ATTR._consoleColor = FOREGROUND_GREEN | thisBackground;
  45. break;
  46. case 33:
  47. case 93:
  48. WIN_ATTR._consoleColor = FOREGROUND_RED | FOREGROUND_GREEN | thisBackground;
  49. break;
  50. case 34:
  51. case 94:
  52. WIN_ATTR._consoleColor = FOREGROUND_BLUE | thisBackground;
  53. break;
  54. case 35:
  55. case 95:
  56. WIN_ATTR._consoleColor = FOREGROUND_BLUE | FOREGROUND_RED | thisBackground;
  57. break;
  58. case 36:
  59. case 96:
  60. WIN_ATTR._consoleColor = FOREGROUND_BLUE | FOREGROUND_GREEN | thisBackground;
  61. break;
  62. case 37:
  63. case 97:
  64. WIN_ATTR._consoleColor = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | thisBackground;
  65. break;
  66. case 101:
  67. thisBackground = BACKGROUND_RED;
  68. break;
  69. }
  70. if ( ( code >= 90 ) && ( code <= 97 ) ) {
  71. WIN_ATTR._consoleAttribute = (WIN_ATTR._defaultAttribute ^ FOREGROUND_INTENSITY) & INTENSITY;
  72. }
  73. code = 0;
  74. }
  75. if (*p == 'm') {
  76. ++p;
  77. break;
  78. }
  79. }
  80. } else {
  81. ++p;
  82. }
  83. auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
  84. SetConsoleTextAttribute(
  85. handle,
  86. WIN_ATTR._consoleAttribute | WIN_ATTR._consoleColor
  87. );
  88. return p;
  89. }
  90. int win_write( char const* str_, int size_ ) {
  91. int count( 0 );
  92. DWORD currentMode( 0 );
  93. HANDLE consoleOut( GetStdHandle( STD_OUTPUT_HANDLE ) );
  94. if ( tty::out && GetConsoleMode( consoleOut, &currentMode ) ) {
  95. UINT inputCodePage( GetConsoleCP() );
  96. UINT outputCodePage( GetConsoleOutputCP() );
  97. SetConsoleCP( 65001 );
  98. SetConsoleOutputCP( 65001 );
  99. DWORD nWritten( 0 );
  100. if ( SetConsoleMode( consoleOut, currentMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING ) ) {
  101. WriteConsoleA( consoleOut, str_, size_, &nWritten, nullptr );
  102. count = nWritten;
  103. SetConsoleMode( consoleOut, currentMode );
  104. } else {
  105. char const* s( str_ );
  106. char const* e( str_ + size_ );
  107. while ( str_ < e ) {
  108. if ( *str_ == 27 ) {
  109. if ( s < str_ ) {
  110. int toWrite( str_ - s );
  111. WriteConsoleA( consoleOut, s, static_cast<DWORD>( toWrite ), &nWritten, nullptr );
  112. count += nWritten;
  113. if ( nWritten != toWrite ) {
  114. s = str_ = nullptr;
  115. break;
  116. }
  117. }
  118. s = HandleEsc( str_ + 1, e );
  119. int escaped( s - str_);
  120. count += escaped;
  121. str_ = s;
  122. } else {
  123. ++ str_;
  124. }
  125. }
  126. if ( s < str_ ) {
  127. WriteConsoleA( consoleOut, s, static_cast<DWORD>( str_ - s ), &nWritten, nullptr );
  128. count += nWritten;
  129. }
  130. }
  131. SetConsoleCP( inputCodePage );
  132. SetConsoleOutputCP( outputCodePage );
  133. } else {
  134. count = _write( 1, str_, size_ );
  135. }
  136. return ( count );
  137. }
  138. }
  139. #endif