mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 01:59:43 +01:00
dd15d67e62
The intention of the `-console` argument was to enable seeing console output on Windows without having to use workarounds. However, this didn't actually work for arguments like `-addresses` and `-version`, because the program would exit first before it could get the chance to create the console. The other issue is that the console closes too quickly before output can be read by the user. So to fix that, we must hold it open and let the user close it when they want to by waiting for an enter press from STDIN.
293 lines
6.3 KiB
C
293 lines
6.3 KiB
C
#include "Vlogging.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef __ANDROID__
|
|
// forward to SDL logging on Android, since stdout/stderr are /dev/null
|
|
#define VLOG_USE_SDL 1
|
|
#endif
|
|
|
|
#ifdef VLOG_USE_SDL
|
|
# include <SDL_log.h>
|
|
#elif defined(_WIN32)
|
|
# define WIN32_LEAN_AND_MEAN
|
|
# include <windows.h>
|
|
#elif defined(__unix__) || defined(__APPLE__)
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
#define COLOR(EXPR) (color_enabled && color_supported ? EXPR : "")
|
|
|
|
#define Color_RESET COLOR("\x1b[0m")
|
|
#define Color_BOLD COLOR("\x1b[1m")
|
|
#define Color_BOLD_YELLOW COLOR("\x1b[1;33m")
|
|
#define Color_BOLD_RED COLOR("\x1b[1;31m")
|
|
#define Color_BOLD_GRAY COLOR("\x1b[1;90m")
|
|
|
|
#ifdef __ANDROID__
|
|
const int color_supported = 0;
|
|
#else
|
|
static int color_supported = 0;
|
|
#endif
|
|
|
|
static int output_enabled = 1;
|
|
static int color_enabled = 1;
|
|
static int debug_enabled = 0;
|
|
static int info_enabled = 1;
|
|
static int warn_enabled = 1;
|
|
static int error_enabled = 1;
|
|
|
|
static void check_color_support(void);
|
|
|
|
void vlog_init(void)
|
|
{
|
|
#ifdef VLOG_USE_SDL
|
|
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE);
|
|
#endif
|
|
check_color_support();
|
|
}
|
|
|
|
void vlog_toggle_output(const int enable_output)
|
|
{
|
|
output_enabled = enable_output;
|
|
}
|
|
|
|
void vlog_toggle_color(const int enable_color)
|
|
{
|
|
color_enabled = enable_color;
|
|
}
|
|
|
|
void vlog_toggle_debug(const int enable_debug)
|
|
{
|
|
debug_enabled = enable_debug;
|
|
}
|
|
|
|
void vlog_toggle_info(const int enable_info)
|
|
{
|
|
info_enabled = enable_info;
|
|
}
|
|
|
|
void vlog_toggle_warn(const int enable_warn)
|
|
{
|
|
warn_enabled = enable_warn;
|
|
}
|
|
|
|
void vlog_toggle_error(const int enable_error)
|
|
{
|
|
error_enabled = enable_error;
|
|
}
|
|
|
|
SDL_PRINTF_VARARG_FUNC(1) void vlog_debug(const char* text, ...)
|
|
{
|
|
va_list list;
|
|
|
|
if (!output_enabled || !debug_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef VLOG_USE_SDL
|
|
va_start(list, text);
|
|
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, text, list);
|
|
va_end(list);
|
|
#else
|
|
printf(Color_BOLD_GRAY);
|
|
printf("[DEBUG]");
|
|
printf(Color_RESET);
|
|
printf(" ");
|
|
|
|
va_start(list, text);
|
|
vprintf(text, list);
|
|
va_end(list);
|
|
|
|
putchar('\n');
|
|
#endif
|
|
}
|
|
|
|
SDL_PRINTF_VARARG_FUNC(1) void vlog_info(const char* text, ...)
|
|
{
|
|
va_list list;
|
|
|
|
if (!output_enabled || !info_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef VLOG_USE_SDL
|
|
va_start(list, text);
|
|
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, text, list);
|
|
va_end(list);
|
|
#else
|
|
printf(Color_BOLD);
|
|
printf("[INFO]");
|
|
printf(Color_RESET);
|
|
printf(" ");
|
|
|
|
va_start(list, text);
|
|
vprintf(text, list);
|
|
va_end(list);
|
|
|
|
putchar('\n');
|
|
#endif
|
|
}
|
|
|
|
SDL_PRINTF_VARARG_FUNC(1) void vlog_warn(const char* text, ...)
|
|
{
|
|
va_list list;
|
|
|
|
if (!output_enabled || !warn_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef VLOG_USE_SDL
|
|
va_start(list, text);
|
|
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, text, list);
|
|
va_end(list);
|
|
#else
|
|
fprintf(stderr, Color_BOLD_YELLOW);
|
|
fprintf(stderr, "[WARN]");
|
|
fprintf(stderr, Color_RESET);
|
|
fprintf(stderr, " ");
|
|
|
|
va_start(list, text);
|
|
vfprintf(stderr, text, list);
|
|
va_end(list);
|
|
|
|
fputc('\n', stderr);
|
|
#endif
|
|
}
|
|
|
|
SDL_PRINTF_VARARG_FUNC(1) void vlog_error(const char* text, ...)
|
|
{
|
|
va_list list;
|
|
|
|
if (!output_enabled || !error_enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef VLOG_USE_SDL
|
|
va_start(list, text);
|
|
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, text, list);
|
|
va_end(list);
|
|
#else
|
|
fprintf(stderr, Color_BOLD_RED);
|
|
fprintf(stderr, "[ERROR]");
|
|
fprintf(stderr, Color_RESET);
|
|
fprintf(stderr, " ");
|
|
|
|
va_start(list, text);
|
|
vfprintf(stderr, text, list);
|
|
va_end(list);
|
|
|
|
fputc('\n', stderr);
|
|
#endif
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
void vlog_open_console(void)
|
|
{
|
|
static int run_once = 0;
|
|
if (run_once)
|
|
{
|
|
return;
|
|
}
|
|
run_once = 1;
|
|
|
|
const BOOL success = AllocConsole();
|
|
if (!success)
|
|
{
|
|
/* Debug, not error, because it might not be an error.
|
|
* (E.g. there is already an attached console.) */
|
|
vlog_debug(
|
|
"Could not open console: AllocConsole() failed with %d",
|
|
GetLastError()
|
|
);
|
|
return;
|
|
}
|
|
|
|
const FILE* handle = freopen("CON", "w", stdout);
|
|
if (handle == NULL)
|
|
{
|
|
vlog_error("Could not redirect STDOUT to console.");
|
|
}
|
|
|
|
handle = freopen("CON", "w", stderr);
|
|
if (handle == NULL)
|
|
{
|
|
vlog_error("Could not redirect STDERR to console.");
|
|
}
|
|
|
|
handle = freopen("CON", "r", stdin);
|
|
if (handle == NULL)
|
|
{
|
|
vlog_error("Could not redirect STDIN to console.");
|
|
}
|
|
|
|
check_color_support();
|
|
|
|
if (!SetConsoleOutputCP(CP_UTF8))
|
|
{
|
|
vlog_warn(
|
|
"Could not set code page for console output to UTF-8: "
|
|
"SetConsoleOutputCP() failed with %d",
|
|
GetLastError()
|
|
);
|
|
}
|
|
}
|
|
#endif /* _WIN32 */
|
|
|
|
static void check_color_support(void)
|
|
{
|
|
#ifdef _WIN32
|
|
/* VT100 colors are supported since Windows 10 build 16257,
|
|
* but it's not enabled by default. So we have to set it. */
|
|
|
|
const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
if (hStdout == INVALID_HANDLE_VALUE)
|
|
{
|
|
vlog_error(
|
|
"Could not set color support: GetStdHandle() failed with %d",
|
|
GetLastError()
|
|
);
|
|
return;
|
|
}
|
|
|
|
const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
|
|
if (hStderr == INVALID_HANDLE_VALUE)
|
|
{
|
|
vlog_error(
|
|
"Could not enable color support: GetStdHandle() failed with %d",
|
|
GetLastError()
|
|
);
|
|
return;
|
|
}
|
|
|
|
/* Older VS releases don't have this defined yet */
|
|
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
|
#endif
|
|
const BOOL success = SetConsoleMode(
|
|
hStdout, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
);
|
|
if (!success)
|
|
{
|
|
/* Debug, not error, because it might not be an error.
|
|
* (E.g. this version of Windows doesn't support VT100 colors.) */
|
|
vlog_debug(
|
|
"Could not enable color support: SetConsoleMode() failed with %d",
|
|
GetLastError()
|
|
);
|
|
return;
|
|
}
|
|
|
|
color_supported = 1;
|
|
#elif (defined(__unix__) || defined(__APPLE__)) && !defined(VLOG_USE_SDL)
|
|
if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO))
|
|
{
|
|
color_supported = 1;
|
|
}
|
|
#endif
|
|
}
|