1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-26 06:28:30 +02:00
VVVVVV/desktop_version/src/Vlogging.c
Misa dd15d67e62 Fix info args not working with -console
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.
2024-06-03 21:42:57 -07:00

294 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
}