diff options
author | Michał Cichoń <michcic@gmail.com> | 2015-12-10 11:57:00 +0100 |
---|---|---|
committer | Michał Cichoń <michcic@gmail.com> | 2015-12-10 11:57:00 +0100 |
commit | 6dee813dad2dd0b741025be046dfe3c7019bddb9 (patch) | |
tree | e075e6f55aea250f5ca1bb628a15327f52f3789e /src/console.c | |
parent | 13e06e633d966a7600794deb43d725cbd89e108c (diff) | |
parent | 754a62188d0fa2bc29c7089a6beccea9622c9911 (diff) | |
download | pianobar-windows-6dee813dad2dd0b741025be046dfe3c7019bddb9.tar.gz pianobar-windows-6dee813dad2dd0b741025be046dfe3c7019bddb9.tar.bz2 pianobar-windows-6dee813dad2dd0b741025be046dfe3c7019bddb9.zip |
Merge branch 'release/2015.12.10'2015.12.10
Diffstat (limited to 'src/console.c')
-rw-r--r-- | src/console.c | 613 |
1 files changed, 308 insertions, 305 deletions
diff --git a/src/console.c b/src/console.c index b05f0a3..07e3c37 100644 --- a/src/console.c +++ b/src/console.c @@ -1,6 +1,6 @@ /* Copyright (c) 2015 - Micha³ Cichoñ <thedmd@interia.pl> + Micha³ Cichoñ <thedmd@interia.pl> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -29,392 +29,395 @@ THE SOFTWARE. #include <process.h> #include "vtparse/vtparse.h" -enum { READ = 0, WRITE }; - -# define BAR_IN_CAPACITY 1024 -# define BAR_OUT_CAPACITY 1024 +# define BAR_BUFFER_CAPACITY 1024 static const int BarTerminalToAttibColor[8] = { - 0 /* black */, 4 /* red */, 2 /* green */, 6 /* yellow */, - 1 /* blue */, 5 /* magenta */, 3 /* cyan */, 7 /* white */ + 0 /* black */, 4 /* red */, 2 /* green */, 6 /* yellow */, + 1 /* blue */, 5 /* magenta */, 3 /* cyan */, 7 /* white */ }; -static struct BarConsoleState { - HANDLE StdIn; - HANDLE StdOut; - - int Pipes[2]; - int OriginalStdOut; - int OriginalStdErr; - - WORD DefaultAttributes; - WORD CurrentAttributes; +static struct BarConsoleState +{ + HANDLE StdIn; + HANDLE StdOut; - HANDLE ConsoleThread; - bool Terminate; + WORD DefaultAttributes; + WORD CurrentAttributes; - vtparse_t Parser; + HANDLE ConsoleThread; + bool Terminate; - char InBuffer[BAR_IN_CAPACITY]; - size_t InBufferSize; + vtparse_t Parser; - char OutBuffer[BAR_OUT_CAPACITY]; - size_t OutBufferSize; + char Buffer[BAR_BUFFER_CAPACITY]; + size_t BufferSize; } g_BarConsole; -static inline void BarOutSetAttributes(WORD attributes) { - g_BarConsole.CurrentAttributes = attributes; - SetConsoleTextAttribute(CONSOLE_REAL_OUTPUT_HANDLE, g_BarConsole.CurrentAttributes); +static inline void BarOutSetAttributes(WORD attributes) +{ + g_BarConsole.CurrentAttributes = attributes; + SetConsoleTextAttribute(BarConsoleGetStdOut(), g_BarConsole.CurrentAttributes); } -static inline void BarOutFlush() { - if (g_BarConsole.OutBufferSize == 0) - return; +static void BarParseCallback(struct vtparse* parser, vtparse_action_t action, unsigned char ch) +{ + if (action == VTPARSE_ACTION_PRINT || action == VTPARSE_ACTION_EXECUTE) + { + putc(ch, stdout); + if (action == VTPARSE_ACTION_EXECUTE) + fflush(stdout); + } + + if (action == VTPARSE_ACTION_CSI_DISPATCH) + { + WORD attribute = g_BarConsole.CurrentAttributes; + int i; + + switch (ch) + { + case 'K': + BarConsoleEraseLine(parser->num_params > 0 ? parser->params[0] : 0); + break; + + case 'm': + for (i = 0; i < parser->num_params; ++i) + { + int p = parser->params[i]; + if (p == 0) + attribute = g_BarConsole.DefaultAttributes; + //else if (p == 1) + // attribute |= FOREGROUND_INTENSITY; + else if (p == 4) + attribute |= COMMON_LVB_UNDERSCORE; + else if (p == 7) + attribute |= COMMON_LVB_REVERSE_VIDEO; + //else if (p == 21) + // attribute &= ~FOREGROUND_INTENSITY; + else if (p == 24) + attribute &= ~COMMON_LVB_UNDERSCORE; + else if (p == 27) + attribute &= ~COMMON_LVB_REVERSE_VIDEO; + else if (p >= 30 && p <= 37) + attribute = (attribute & ~0x07) | BarTerminalToAttibColor[p - 30]; + else if (p >= 40 && p <= 47) + attribute = (attribute & ~0x70) | (BarTerminalToAttibColor[p - 40] << 4); + else if (p >= 90 && p <= 97) + attribute = (attribute & ~0x07) | BarTerminalToAttibColor[p - 90] | FOREGROUND_INTENSITY; + else if (p >= 100 && p <= 107) + attribute = ((attribute & ~0x70) | (BarTerminalToAttibColor[p - 100] << 4)) | BACKGROUND_INTENSITY; + } + fflush(stdout); + BarOutSetAttributes(attribute); + break; + } + } +} - _write(g_BarConsole.OriginalStdOut, g_BarConsole.OutBuffer, g_BarConsole.OutBufferSize); +void BarConsoleInit() +{ + unsigned threadId = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + memset(&g_BarConsole, 0, sizeof(g_BarConsole)); - g_BarConsole.OutBufferSize = 0; -} + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); -static inline void BarOutPut(char c) { - if (g_BarConsole.OutBufferSize >= BAR_OUT_CAPACITY) - BarOutFlush(); + g_BarConsole.StdIn = GetStdHandle(STD_INPUT_HANDLE); + g_BarConsole.StdOut = GetStdHandle(STD_OUTPUT_HANDLE); - g_BarConsole.OutBuffer[g_BarConsole.OutBufferSize++] = c; -} + GetConsoleScreenBufferInfo(g_BarConsole.StdOut, &csbi); -static inline void BarOutPuts(const char* c) { - size_t length = strlen(c); - size_t i; + g_BarConsole.DefaultAttributes = csbi.wAttributes; + g_BarConsole.CurrentAttributes = csbi.wAttributes; - for (i = 0; i < length; ++i) - BarOutPut(c[i]); + vtparse_init(&g_BarConsole.Parser, BarParseCallback); } -static void BarParseCallback(struct vtparse* parser, vtparse_action_t action, unsigned char ch) { - if (action == VTPARSE_ACTION_PRINT || action == VTPARSE_ACTION_EXECUTE) - { - BarOutPut(ch); - if (action == VTPARSE_ACTION_EXECUTE) - BarOutFlush(); - } - - if (action == VTPARSE_ACTION_CSI_DISPATCH) - { - WORD attribute = g_BarConsole.CurrentAttributes; - int i; - - switch (ch) - { - case 'K': - BarConsoleEraseLine(parser->num_params > 0 ? parser->params[0] : 0); - break; - - case 'm': - for (i = 0; i < parser->num_params; ++i) { - int p = parser->params[i]; - if (p == 0) - attribute = g_BarConsole.DefaultAttributes; - //else if (p == 1) - // attribute |= FOREGROUND_INTENSITY; - else if (p == 4) - attribute |= COMMON_LVB_UNDERSCORE; - else if (p == 7) - attribute |= COMMON_LVB_REVERSE_VIDEO; - //else if (p == 21) - // attribute &= ~FOREGROUND_INTENSITY; - else if (p == 24) - attribute &= ~COMMON_LVB_UNDERSCORE; - else if (p == 27) - attribute &= ~COMMON_LVB_REVERSE_VIDEO; - else if (p >= 30 && p <= 37) - attribute = (attribute & ~0x07) | BarTerminalToAttibColor[p - 30]; - else if (p >= 40 && p <= 47) - attribute = (attribute & ~0x70) | (BarTerminalToAttibColor[p - 40] << 4); - else if (p >= 90 && p <= 97) - attribute = (attribute & ~0x07) | BarTerminalToAttibColor[p - 90] | FOREGROUND_INTENSITY; - else if (p >= 100 && p <= 107) - attribute = ((attribute & ~0x70) | (BarTerminalToAttibColor[p - 100] << 4)) | BACKGROUND_INTENSITY; - } - BarOutFlush(); - BarOutSetAttributes(attribute); - break; - } - } +void BarConsoleDestroy() +{ } -static unsigned __stdcall BarConsoleThread(void* args) { - - while (!g_BarConsole.Terminate) { +HANDLE BarConsoleGetStdIn() +{ + return g_BarConsole.StdIn; +} - int bytes = _read(g_BarConsole.Pipes[READ], g_BarConsole.InBuffer, BAR_IN_CAPACITY); +HANDLE BarConsoleGetStdOut() +{ + return g_BarConsole.StdOut; +} - if (bytes > 0) - vtparse(&g_BarConsole.Parser, g_BarConsole.InBuffer, bytes); +void BarConsoleSetTitle(const char* title) +{ + size_t len = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); - BarOutFlush(); - } + TCHAR* wTitle = malloc((len + 1) * sizeof(TCHAR)); + if (NULL != wTitle) + { + MultiByteToWideChar(CP_UTF8, 0, title, -1, wTitle, len); + SetConsoleTitleW(wTitle); - return 0; + free(wTitle); + } + else + SetConsoleTitleA(title); } -void BarConsoleInit() { - unsigned threadId = 0; - CONSOLE_SCREEN_BUFFER_INFO csbi; - memset(&g_BarConsole, 0, sizeof(g_BarConsole)); +void BarConsoleSetSize(int width, int height) +{ + HANDLE handle; + SMALL_RECT r; + COORD c, s; + CONSOLE_SCREEN_BUFFER_INFO csbi; - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); + handle = BarConsoleGetStdOut(); - g_BarConsole.StdIn = GetStdHandle(STD_INPUT_HANDLE); - g_BarConsole.StdOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (!GetConsoleScreenBufferInfo(handle, &csbi)) + return; - GetConsoleScreenBufferInfo(g_BarConsole.StdOut, &csbi); + s.X = csbi.srWindow.Right - csbi.srWindow.Left + 1; + s.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; - g_BarConsole.DefaultAttributes = csbi.wAttributes; - g_BarConsole.CurrentAttributes = csbi.wAttributes; + if (s.X > width && s.Y > height) + return; - if (_pipe(g_BarConsole.Pipes, 65536, O_BINARY) != -1) { - g_BarConsole.OriginalStdOut = _dup(_fileno(stdout)); - g_BarConsole.OriginalStdErr = _dup(_fileno(stderr)); + c.X = width; + c.Y = height; - fflush(stdout); - fflush(stderr); + if (s.X > c.X) + c.X = s.X; + if (s.Y > c.Y) + c.Y = s.Y; - dup2(g_BarConsole.Pipes[WRITE], fileno(stdout)); - dup2(g_BarConsole.Pipes[WRITE], fileno(stderr)); + SetConsoleScreenBufferSize(handle, c); - g_BarConsole.ConsoleThread = (HANDLE)_beginthreadex(NULL, 0, BarConsoleThread, NULL, 0, &threadId); - if (!g_BarConsole.ConsoleThread) - BarConsoleDestroy(); - } - - vtparse_init(&g_BarConsole.Parser, BarParseCallback); + r.Left = 0; + r.Top = 0; + r.Right = c.X - 1; + r.Bottom = c.Y - 1; + SetConsoleWindowInfo(handle, TRUE, &r); } -void BarConsoleDestroy() { - if (g_BarConsole.ConsoleThread) { - g_BarConsole.Terminate = true; - fputs(" ", stderr); - fputs(" ", stdout); - - fflush(stdout); - fflush(stderr); - - WaitForSingleObject(g_BarConsole.ConsoleThread, INFINITE); - } - - if (g_BarConsole.OriginalStdErr > 0) { - fflush(stderr); - dup2(g_BarConsole.OriginalStdErr, fileno(stderr)); - _close(g_BarConsole.OriginalStdErr); - g_BarConsole.OriginalStdErr = 0; - } - if (g_BarConsole.OriginalStdOut > 0) { - fflush(stdout); - dup2(g_BarConsole.OriginalStdOut, fileno(stdout)); - _close(g_BarConsole.OriginalStdOut); - g_BarConsole.OriginalStdOut = 0; - } - if (g_BarConsole.Pipes[0] > 0) { - _close(g_BarConsole.Pipes[0]); - g_BarConsole.Pipes[0] = 0; - } - if (g_BarConsole.Pipes[1] > 0) { - _close(g_BarConsole.Pipes[1]); - g_BarConsole.Pipes[1] = 0; - } +void BarConsoleSetCursorPosition(COORD position) +{ + SetConsoleCursorPosition(BarConsoleGetStdOut(), position); } -HANDLE BarConsoleGetStdIn () { - return g_BarConsole.StdIn; -} +COORD BarConsoleGetCursorPosition() +{ + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + COORD result = { -1, -1 }; + + if (GetConsoleScreenBufferInfo(BarConsoleGetStdOut(), &consoleInfo)) + result = consoleInfo.dwCursorPosition; -HANDLE BarConsoleGetStdOut () { - return GetStdHandle(STD_OUTPUT_HANDLE);//g_BarConsole.StdOut; + return result; } -void BarConsoleSetTitle (const char* title) { - size_t len = MultiByteToWideChar (CP_UTF8, 0, title, -1, NULL, 0); +COORD BarConsoleMoveCursor(int xoffset) +{ + COORD position; - TCHAR* wTitle = malloc((len + 1) * sizeof(TCHAR)); - if (NULL != wTitle) - { - MultiByteToWideChar (CP_UTF8, 0, title, -1, wTitle, len); - SetConsoleTitleW (wTitle); + position = BarConsoleGetCursorPosition(); + position.X += xoffset; + BarConsoleSetCursorPosition(position); - free(wTitle); - } - else - SetConsoleTitleA (title); + return position; } -void BarConsoleSetSize (int width, int height) { - HANDLE handle; - SMALL_RECT r; - COORD c, s; - CONSOLE_SCREEN_BUFFER_INFO csbi; +void BarConsoleEraseCharacter() +{ + TCHAR buffer[256]; + WORD buffer2[256]; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + COORD coords; + HANDLE handle = BarConsoleGetStdOut(); + int length, read, write; + + if (!GetConsoleScreenBufferInfo(handle, &csbiInfo)) + return; + + length = csbiInfo.dwSize.X - csbiInfo.dwCursorPosition.X - 1; + read = csbiInfo.dwCursorPosition.X + 1; + write = csbiInfo.dwCursorPosition.X; + + while (length >= 0) + { + int size = min(length, 256); + DWORD chRead = 0, chWritten = 0; + coords = csbiInfo.dwCursorPosition; + coords.X = read; + ReadConsoleOutputAttribute(handle, buffer2, size, coords, &chRead); + ReadConsoleOutputCharacter(handle, buffer, size, coords, &chRead); + + if (chRead == 0) + break; + + coords.X = write; + WriteConsoleOutputAttribute(handle, buffer2, chRead, coords, &chWritten); + WriteConsoleOutputCharacter(handle, buffer, chRead, coords, &chWritten); + + read += chRead; + write += chRead; + length -= chRead; + } +} - handle = CONSOLE_REAL_OUTPUT_HANDLE; +void BarConsoleEraseLine(int mode) +{ + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + DWORD writen, length; + COORD coords; - if (!GetConsoleScreenBufferInfo(handle, &csbi)) - return; + HANDLE handle = BarConsoleGetStdOut(); - s.X = csbi.srWindow.Right - csbi.srWindow.Left + 1; - s.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + if (!GetConsoleScreenBufferInfo(handle, &csbiInfo)) + return; - if (s.X > width && s.Y > height) - return; + writen = 0; + coords.X = 0; + coords.Y = csbiInfo.dwCursorPosition.Y; - c.X = width; - c.Y = height; + switch (mode) + { + default: + case 0: /* from cursor */ + coords.X = BarConsoleGetCursorPosition().X; + length = csbiInfo.dwSize.X - coords.X; + break; - if (s.X > c.X) - c.X = s.X; - if (s.Y > c.Y) - c.Y = s.Y; + case 1: /* to cursor */ + coords.X = 0; + length = BarConsoleGetCursorPosition().X; + break; - SetConsoleScreenBufferSize(handle, c); + case 2: /* whole line */ + coords.X = 0; + length = csbiInfo.dwSize.X; + break; + } - r.Left = 0; - r.Top = 0; - r.Right = c.X - 1; - r.Bottom = c.Y - 1; - SetConsoleWindowInfo(handle, TRUE, &r); -} + FillConsoleOutputCharacter(handle, ' ', length, coords, &writen); + FillConsoleOutputAttribute(handle, csbiInfo.wAttributes, csbiInfo.dwSize.X, coords, &writen); -void BarConsoleSetCursorPosition (COORD position) { - SetConsoleCursorPosition(CONSOLE_REAL_OUTPUT_HANDLE, position); + SetConsoleCursorPosition(handle, coords); } -COORD BarConsoleGetCursorPosition () { - CONSOLE_SCREEN_BUFFER_INFO consoleInfo; - COORD result = { -1, -1 }; +void BarConsoleSetClipboard(const char* text) +{ + WCHAR* wideString; + HANDLE stringHandle; + size_t wideSize, wideBytes; - if (GetConsoleScreenBufferInfo(CONSOLE_REAL_OUTPUT_HANDLE, &consoleInfo)) - result = consoleInfo.dwCursorPosition; + wideSize = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0); + wideBytes = wideSize * sizeof(WCHAR); + wideString = malloc(wideBytes); + if (!wideString) + return; - return result; -} + MultiByteToWideChar(CP_UTF8, 0, text, -1, wideString, wideSize); -COORD BarConsoleMoveCursor (int xoffset) { - COORD position; + stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideBytes); + if (!stringHandle) + { + free(wideString); + return; + } - position = BarConsoleGetCursorPosition(); - position.X += xoffset; - BarConsoleSetCursorPosition(position); + memcpy(GlobalLock(stringHandle), wideString, wideBytes); - return position; -} + GlobalUnlock(stringHandle); -void BarConsoleEraseCharacter () { - TCHAR buffer[256]; - WORD buffer2[256]; - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD coords; - HANDLE handle = CONSOLE_REAL_OUTPUT_HANDLE; - int length, read, write; - - if (!GetConsoleScreenBufferInfo(handle, &csbiInfo)) - return; - - length = csbiInfo.dwSize.X - csbiInfo.dwCursorPosition.X - 1; - read = csbiInfo.dwCursorPosition.X + 1; - write = csbiInfo.dwCursorPosition.X; - - while (length >= 0) { - int size = min(length, 256); - DWORD chRead = 0, chWritten = 0; - coords = csbiInfo.dwCursorPosition; - coords.X = read; - ReadConsoleOutputAttribute(handle, buffer2, size, coords, &chRead); - ReadConsoleOutputCharacter(handle, buffer, size, coords, &chRead); - - if (chRead == 0) - break; - - coords.X = write; - WriteConsoleOutputAttribute(handle, buffer2, chRead, coords, &chWritten); - WriteConsoleOutputCharacter(handle, buffer, chRead, coords, &chWritten); - - read += chRead; - write += chRead; - length -= chRead; - } -} + if (!OpenClipboard(NULL)) + { + GlobalFree(stringHandle); + free(wideString); + return; + } -void BarConsoleEraseLine (int mode) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - DWORD writen, length; - COORD coords; + EmptyClipboard(); - HANDLE handle = CONSOLE_REAL_OUTPUT_HANDLE; + SetClipboardData(CF_UNICODETEXT, stringHandle); - if (!GetConsoleScreenBufferInfo(handle, &csbiInfo)) - return; + CloseClipboard(); - writen = 0; - coords.X = 0; - coords.Y = csbiInfo.dwCursorPosition.Y; + free(wideString); +} - switch (mode) { - default: - case 0: /* from cursor */ - coords.X = BarConsoleGetCursorPosition().X; - length = csbiInfo.dwSize.X - coords.X; - break; +void BarConsoleFlush() +{ + char buffer[BAR_BUFFER_CAPACITY]; + size_t bufferSize = 0; - case 1: /* to cursor */ - coords.X = 0; - length = BarConsoleGetCursorPosition().X; - break; + if (g_BarConsole.BufferSize == 0) + return; - case 2: /* whole line */ - coords.X = 0; - length = csbiInfo.dwSize.X; - break; - } + bufferSize = g_BarConsole.BufferSize; + memcpy(buffer, g_BarConsole.Buffer, bufferSize); - FillConsoleOutputCharacter(handle, ' ', length, coords, &writen); - FillConsoleOutputAttribute(handle, csbiInfo.wAttributes, csbiInfo.dwSize.X, coords, &writen); + g_BarConsole.BufferSize = 0; - SetConsoleCursorPosition(handle, coords); + vtparse(&g_BarConsole.Parser, buffer, bufferSize); } -void BarConsoleSetClipboard(const char* text) { - WCHAR* wideString; - HANDLE stringHandle; - size_t wideSize, wideBytes; +void BarConsolePutc(char c) +{ + if (g_BarConsole.BufferSize >= BAR_BUFFER_CAPACITY) + BarConsoleFlush(); - wideSize = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0); - wideBytes = wideSize * sizeof(WCHAR); - wideString = malloc(wideBytes); - if (!wideString) - return; - - MultiByteToWideChar(CP_UTF8, 0, text, -1, wideString, wideSize); + g_BarConsole.Buffer[g_BarConsole.BufferSize++] = c; +} - stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideBytes); - if (!stringHandle) { - free(wideString); - return; - } +void BarConsolePuts(const char* c) +{ + size_t length = strlen(c); + size_t i; - memcpy(GlobalLock(stringHandle), wideString, wideBytes); + for (i = 0; i < length; ++i) + BarConsolePutc(c[i]); +} - GlobalUnlock(stringHandle); +static char* BarConsoleFormat(char* buffer, size_t buffer_size, const char* format, va_list args) +{ + bool allocated = false; + + int chars_writen; + while ((chars_writen = _vsnprintf(buffer, buffer_size - 1, format, args)) < 0) + { + size_t new_buffer_size = buffer_size * 3 / 2; + if (new_buffer_size < buffer_size) + { // handle overflow + chars_writen = buffer_size; + break; + } + + if (allocated) + buffer = realloc(buffer, new_buffer_size); + else + buffer = malloc(new_buffer_size); + buffer_size = new_buffer_size; + } + + return buffer; +} - if (!OpenClipboard(NULL)) { - GlobalFree(stringHandle); - free(wideString); - return; - } +void BarConsolePrint(const char* format, ...) +{ + va_list args; + va_start(args, format); + BarConsolePrintV(format, args); + va_end(args); +} - EmptyClipboard(); +void BarConsolePrintV(const char* format, va_list args) +{ + char localBuffer[BAR_BUFFER_CAPACITY]; + size_t bufferSize = BAR_BUFFER_CAPACITY, i = 0; - SetClipboardData(CF_UNICODETEXT, stringHandle); + char* buffer = BarConsoleFormat(localBuffer, bufferSize, format, args); - CloseClipboard(); + BarConsolePuts(buffer); - free(wideString); + if (buffer != localBuffer) + free(buffer); }
\ No newline at end of file |