From aefb64c36944482b97d2d90586b36321f39587a7 Mon Sep 17 00:00:00 2001 From: Tanguy Pruvot Date: Tue, 26 Aug 2014 02:40:06 +0200 Subject: [PATCH] windows: implements the color option based on old git implementation (2009) Signed-off-by: Tanguy Pruvot --- ccminer.vcxproj | 5 +- ccminer.vcxproj.filters | 6 + compat/winansi.c | 384 ++++++++++++++++++++++++++++++++++++++++ compat/winansi.h | 32 ++++ cpu-miner.c | 1 + util.c | 3 +- 6 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 compat/winansi.c create mode 100644 compat/winansi.h diff --git a/ccminer.vcxproj b/ccminer.vcxproj index 389bf5b..3ffd45a 100644 --- a/ccminer.vcxproj +++ b/ccminer.vcxproj @@ -158,8 +158,9 @@ copy "$(CudaToolkitBinDir)\cudart64*.dll" "$(OutDir)" true true Console - cudart.lib;cuda.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;pthreadVC2.lib;pthreadVCE2.lib;libcurl.lib;ws2_32.lib;Wldap32.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies) + cudart.lib;cuda.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;pthreadVC2.lib;libcurl.lib;ws2_32.lib;Wldap32.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies) ..\pthreads\Pre-built.2\lib\x86;..\curl-7.29.0\build\lib\Release;..\OpenSSL-Win32\lib\VC\static;%(AdditionalLibraryDirectories);$(CudaToolkitLibDir) + /NODEFAULTLIB:LIBCMT %(AdditionalOptions) echo copy "$(CudaToolkitBinDir)\cudart32*.dll" "$(OutDir)" @@ -229,6 +230,7 @@ copy "$(CudaToolkitBinDir)\cudart64*.dll" "$(OutDir)" + /Tp %(AdditionalOptions) false @@ -280,6 +282,7 @@ copy "$(CudaToolkitBinDir)\cudart64*.dll" "$(OutDir)" + diff --git a/ccminer.vcxproj.filters b/ccminer.vcxproj.filters index cee7bbd..eaf77b7 100644 --- a/ccminer.vcxproj.filters +++ b/ccminer.vcxproj.filters @@ -177,6 +177,9 @@ Source Files\sph + + Source Files + @@ -290,6 +293,9 @@ Header Files\sph + + Header Files\compat + diff --git a/compat/winansi.c b/compat/winansi.c new file mode 100644 index 0000000..c0ea115 --- /dev/null +++ b/compat/winansi.c @@ -0,0 +1,384 @@ +/** + * Old Git implementation of windows terminal colors (2009) + * before use of a threaded wrapper. + */ + +#undef NOGDI +#include +#include +#include +#include +#include +#include + +#include "compat/winansi.h" +/* +* Copyright 2008 Peter Harris +*/ + + +/* +Functions to be wrapped: +*/ +#undef printf +#undef fprintf +#undef fputs +#undef vfprintf +/* TODO: write */ + +/* +ANSI codes used by git: m, K + +This file is git-specific. Therefore, this file does not attempt +to implement any codes that are not used by git. +*/ + +static HANDLE console; +static WORD plain_attr; +static WORD attr; +static int negative; + +static void init(void) +{ + CONSOLE_SCREEN_BUFFER_INFO sbi; + + static int initialized = 0; + if (initialized) + return; + + console = GetStdHandle(STD_OUTPUT_HANDLE); + if (console == INVALID_HANDLE_VALUE) + console = NULL; + + if (!console) + return; + + GetConsoleScreenBufferInfo(console, &sbi); + attr = plain_attr = sbi.wAttributes; + negative = 0; + + initialized = 1; +} + +static int write_console(const char *str, int len) +{ + /* convert utf-8 to utf-16, write directly to console */ + int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); + wchar_t *wbuf = (wchar_t *)alloca(wlen * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen); + + WriteConsoleW(console, wbuf, wlen, NULL, NULL); + + /* return original (utf-8 encoded) length */ + return len; +} + +#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) + +static void set_console_attr(void) +{ + WORD attributes = attr; + if (negative) { + attributes &= ~FOREGROUND_ALL; + attributes &= ~BACKGROUND_ALL; + + /* This could probably use a bitmask + instead of a series of ifs */ + if (attr & FOREGROUND_RED) + attributes |= BACKGROUND_RED; + if (attr & FOREGROUND_GREEN) + attributes |= BACKGROUND_GREEN; + if (attr & FOREGROUND_BLUE) + attributes |= BACKGROUND_BLUE; + + if (attr & BACKGROUND_RED) + attributes |= FOREGROUND_RED; + if (attr & BACKGROUND_GREEN) + attributes |= FOREGROUND_GREEN; + if (attr & BACKGROUND_BLUE) + attributes |= FOREGROUND_BLUE; + } + SetConsoleTextAttribute(console, attributes); +} + +static void erase_in_line(void) +{ + CONSOLE_SCREEN_BUFFER_INFO sbi; + DWORD dummy; /* Needed for Windows 7 (or Vista) regression */ + + if (!console) + return; + + GetConsoleScreenBufferInfo(console, &sbi); + FillConsoleOutputCharacterA(console, ' ', + sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition, + &dummy); +} + + +static const char *set_attr(const char *str) +{ + const char *func; + size_t len = strspn(str, "0123456789;"); + func = str + len; + + switch (*func) { + case 'm': + do { + long val = strtol(str, (char **)&str, 10); + switch (val) { + case 0: /* reset */ + attr = plain_attr; + negative = 0; + break; + case 1: /* bold */ + attr |= FOREGROUND_INTENSITY; + break; + case 2: /* faint */ + case 22: /* normal */ + attr &= ~FOREGROUND_INTENSITY; + break; + case 3: /* italic */ + /* Unsupported */ + break; + case 4: /* underline */ + case 21: /* double underline */ + /* Wikipedia says this flag does nothing */ + /* Furthermore, mingw doesn't define this flag + attr |= COMMON_LVB_UNDERSCORE; */ + break; + case 24: /* no underline */ + /* attr &= ~COMMON_LVB_UNDERSCORE; */ + break; + case 5: /* slow blink */ + case 6: /* fast blink */ + /* We don't have blink, but we do have + background intensity */ + attr |= BACKGROUND_INTENSITY; + break; + case 25: /* no blink */ + attr &= ~BACKGROUND_INTENSITY; + break; + case 7: /* negative */ + negative = 1; + break; + case 27: /* positive */ + negative = 0; + break; + case 8: /* conceal */ + case 28: /* reveal */ + /* Unsupported */ + break; + case 30: /* Black */ + attr &= ~FOREGROUND_ALL; + break; + case 31: /* Red */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED; + break; + case 32: /* Green */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_GREEN; + break; + case 33: /* Yellow */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED | FOREGROUND_GREEN; + break; + case 34: /* Blue */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_BLUE; + break; + case 35: /* Magenta */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_RED | FOREGROUND_BLUE; + break; + case 36: /* Cyan */ + attr &= ~FOREGROUND_ALL; + attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + case 37: /* White */ + attr |= FOREGROUND_RED | + FOREGROUND_GREEN | + FOREGROUND_BLUE; + break; + case 38: /* Unknown */ + break; + case 39: /* reset */ + attr &= ~FOREGROUND_ALL; + attr |= (plain_attr & FOREGROUND_ALL); + break; + case 40: /* Black */ + attr &= ~BACKGROUND_ALL; + break; + case 41: /* Red */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED; + break; + case 42: /* Green */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_GREEN; + break; + case 43: /* Yellow */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED | BACKGROUND_GREEN; + break; + case 44: /* Blue */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_BLUE; + break; + case 45: /* Magenta */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_RED | BACKGROUND_BLUE; + break; + case 46: /* Cyan */ + attr &= ~BACKGROUND_ALL; + attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; + break; + case 47: /* White */ + attr |= BACKGROUND_RED | + BACKGROUND_GREEN | + BACKGROUND_BLUE; + break; + case 48: /* Unknown */ + break; + case 49: /* reset */ + attr &= ~BACKGROUND_ALL; + attr |= (plain_attr & BACKGROUND_ALL); + break; + default: + /* Unsupported code */ + break; + } + str++; + } while (*(str - 1) == ';'); + + set_console_attr(); + break; + case 'K': + erase_in_line(); + break; + default: + /* Unsupported code */ + break; + } + + return func + 1; +} + +static int ansi_emulate(const char *str, FILE *stream) +{ + int rv = 0; + const char *pos = str; + + fflush(stream); + + while (*pos) { + pos = strstr(str, "\033["); + if (pos) { + int len = (int) (pos - str); + + if (len) { + int out_len = write_console(str, len); + rv += out_len; + if (out_len < len) + return rv; + } + + str = pos + 2; + rv += 2; + + pos = set_attr(str); + rv += (int) (pos - str); + str = pos; + } + else { + int len = (int) strlen(str); + rv += write_console(str, len); + return rv; + } + } + return rv; +} + +int winansi_fputs(const char *str, FILE *stream) +{ + int rv; + + if (!isatty(fileno(stream))) + return fputs(str, stream); + + init(); + + if (!console) + return fputs(str, stream); + + rv = ansi_emulate(str, stream); + + if (rv >= 0) + return 0; + else + return EOF; +} + +int winansi_vfprintf(FILE *stream, const char *format, va_list list) +{ + int len, rv; + char small_buf[256]; + char *buf = small_buf; + va_list cp; + + if (!isatty(fileno(stream))) + goto abort; + + init(); + + if (!console) + goto abort; + + va_copy(cp, list); + len = vsnprintf(small_buf, sizeof(small_buf), format, cp); + va_end(cp); + + if (len > sizeof(small_buf) - 1) { + buf = malloc(len + 1); + if (!buf) + goto abort; + + len = vsnprintf(buf, len + 1, format, list); + } + + rv = ansi_emulate(buf, stream); + + if (buf != small_buf) + free(buf); + return rv; + +abort: + rv = vfprintf(stream, format, list); + return rv; +} + +int winansi_fprintf(FILE *stream, const char *format, ...) +{ + va_list list; + int rv; + + va_start(list, format); + rv = winansi_vfprintf(stream, format, list); + va_end(list); + + return rv; +} + +int winansi_printf(const char *format, ...) +{ + va_list list; + int rv; + + va_start(list, format); + rv = winansi_vfprintf(stdout, format, list); + va_end(list); + + return rv; +} \ No newline at end of file diff --git a/compat/winansi.h b/compat/winansi.h new file mode 100644 index 0000000..c28dd15 --- /dev/null +++ b/compat/winansi.h @@ -0,0 +1,32 @@ +/* + * ANSI emulation wrappers + */ +#ifdef WIN32 +#include +#include +#include + +#define isatty(fd) _isatty(fd) +#define fileno(fd) _fileno(fd) + +#ifdef __cplusplus +extern "C" { +#endif + int winansi_fputs(const char *str, FILE *stream); + int winansi_printf(const char *format, ...); + int winansi_fprintf(FILE *stream, const char *format, ...); + int winansi_vfprintf(FILE *stream, const char *format, va_list list); +#ifdef __cplusplus +} +#endif + +#undef fputs +#undef fprintf +#undef vfprintf + +#define fputs winansi_fputs +#define printf winansi_printf +#define fprintf winansi_fprintf +#define vfprintf winansi_vfprintf + +#endif \ No newline at end of file diff --git a/cpu-miner.c b/cpu-miner.c index ad388fc..9eb0a58 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -23,6 +23,7 @@ #ifdef WIN32 #include #include +#include "compat/winansi.h" BOOL WINAPI ConsoleHandler(DWORD); #else #include diff --git a/util.c b/util.c index 70d4091..5cb9bd7 100644 --- a/util.c +++ b/util.c @@ -22,7 +22,8 @@ #include #include #include -#if defined(WIN32) +#ifdef WIN32 +#include "compat/winansi.h" #include #include #else