Refactored the terminal initialization code. Also, we will now properly shut down the terminal at the end.

This commit is contained in:
LoRd_MuldeR 2014-12-21 17:19:04 +01:00
parent bc3701305d
commit 1c175c651b
4 changed files with 94 additions and 43 deletions

View File

@ -37,7 +37,7 @@ namespace MUtils
typedef int (main_function_t)(int &argc, char **argv); typedef int (main_function_t)(int &argc, char **argv);
//Startup Application //Startup Application
MUTILS_API int startup(int &argc, char **argv, main_function_t *const entry_point, const bool &debugConsole); MUTILS_API int startup(int &argc, char **argv, main_function_t *const entry_point, const char* const appName, const bool &debugConsole);
//Initialize Qt //Initialize Qt
MUTILS_API QApplication *create_qt(int &argc, char **argv, const QString &appName); MUTILS_API QApplication *create_qt(int &argc, char **argv, const QString &appName);

View File

@ -34,7 +34,7 @@ namespace MUtils
namespace Terminal namespace Terminal
{ {
//Setup terminal //Setup terminal
MUTILS_API void setup(int &argc, char **argv, const bool forceEnabled); MUTILS_API void setup(int &argc, char **argv, const char* const appName, const bool forceEnabled);
//Terminal output //Terminal output
MUTILS_API void write(const int &type, const char *const message); MUTILS_API void write(const int &type, const char *const message);

View File

@ -64,19 +64,19 @@ static bool qt_event_filter(void *message, long *result)
// STARTUP FUNCTION // STARTUP FUNCTION
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static int startup_main(int &argc, char **argv, MUtils::Startup::main_function_t *const entry_point, const bool &debugConsole) static int startup_main(int &argc, char **argv, MUtils::Startup::main_function_t *const entry_point, const char* const appName, const bool &debugConsole)
{ {
qInstallMsgHandler(qt_message_handler); qInstallMsgHandler(qt_message_handler);
MUtils::Terminal::setup(argc, argv, MUTILS_DEBUG || debugConsole); MUtils::Terminal::setup(argc, argv, appName, MUTILS_DEBUG || debugConsole);
return entry_point(argc, argv); return entry_point(argc, argv);
} }
static int startup_helper(int &argc, char **argv, MUtils::Startup::main_function_t *const entry_point, const bool &debugConsole) static int startup_helper(int &argc, char **argv, MUtils::Startup::main_function_t *const entry_point, const char* const appName, const bool &debugConsole)
{ {
int iResult = -1; int iResult = -1;
try try
{ {
iResult = startup_main(argc, argv, entry_point, debugConsole); iResult = startup_main(argc, argv, entry_point, appName, debugConsole);
} }
catch(const std::exception &error) catch(const std::exception &error)
{ {
@ -91,21 +91,21 @@ static int startup_helper(int &argc, char **argv, MUtils::Startup::main_function
return iResult; return iResult;
} }
int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entry_point, const bool &debugConsole) int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entry_point, const char* const appName, const bool &debugConsole)
{ {
int iResult = -1; int iResult = -1;
#if (MUTILS_DEBUG) #if (MUTILS_DEBUG)
#ifdef _MSC_VER #ifdef _MSC_VER
_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF || _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF || _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
#endif //_MSCVER #endif //_MSCVER
iResult = startup_main(argc, argv, entry_point, debugConsole); iResult = startup_main(argc, argv, entry_point, appName, debugConsole);
#else //MUTILS_DEBUG #else //MUTILS_DEBUG
#ifdef _MSC_VER #ifdef _MSC_VER
__try __try
{ {
MUtils::ErrorHandler::initialize(); MUtils::ErrorHandler::initialize();
MUtils::OS::check_debugger(); MUtils::OS::check_debugger();
iResult = startup_helper(argc, argv, entry_point, debugConsole); iResult = startup_helper(argc, argv, entry_point, appName, debugConsole);
} }
__except(1) __except(1)
{ {
@ -115,7 +115,7 @@ int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entr
#else //_MSCVER #else //_MSCVER
MUtils::ErrorHandler::initialize(); MUtils::ErrorHandler::initialize();
MUtils::OS::check_debugger(); MUtils::OS::check_debugger();
iResult = startup_helper(argc, argv, entry_point, debugConsole); iResult = startup_helper(argc, argv, entry_point, appName, debugConsole);
#endif //_MSCVER #endif //_MSCVER
#endif //MUTILS_DEBUG #endif //MUTILS_DEBUG
return iResult; return iResult;

View File

@ -45,9 +45,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <ctime> #include <ctime>
//Lock
static MUtils::Internal::CriticalSection g_terminal_lock;
#ifdef _MSC_VER #ifdef _MSC_VER
#define stricmp(X,Y) _stricmp((X),(Y)) #define stricmp(X,Y) _stricmp((X),(Y))
#endif #endif
@ -102,16 +99,79 @@ static const char *clean_str(char *str)
return str; return str;
} }
///////////////////////////////////////////////////////////////////////////////
// HELPER MACROS
///////////////////////////////////////////////////////////////////////////////
#define REPLACE_STANDARD_STREAM(TYPE, HANDLE) do \
{ \
const int fd_##TYPE = _open_osfhandle((intptr_t)GetStdHandle(HANDLE), flags); \
FILE *const file_##TYPE = (fd_##TYPE >= 0) ? _fdopen(fd_##TYPE, "wb") : NULL; \
if(file_##TYPE) \
{ \
g_terminal_backup_file_##TYPE = *(std##TYPE); \
*(std##TYPE) = *(file_##TYPE); \
g_terminal_filebuf_##TYPE.reset(new std::filebuf(file_##TYPE)); \
g_terminal_backup_fbuf_##TYPE = std::c##TYPE.rdbuf(); \
std::c##TYPE.rdbuf(g_terminal_filebuf_##TYPE.data()); \
} \
} \
while(0)
#define RESTORE_STANDARD_STREAM(TYPE) do \
{ \
if(!g_terminal_filebuf_##TYPE.isNull()) \
{ \
*(std##TYPE) = g_terminal_backup_file_##TYPE; \
std::c##TYPE.rdbuf(g_terminal_backup_fbuf_##TYPE); \
g_terminal_filebuf_##TYPE.reset(NULL); \
} \
} \
while(0)
///////////////////////////////////////////////////////////////////////////////
// TERMINAL VARIABLES
///////////////////////////////////////////////////////////////////////////////
//Critical section
static MUtils::Internal::CriticalSection g_terminal_lock;
//Terminal replacement streams
static bool g_terminal_attached = false;
static QScopedPointer<std::filebuf> g_terminal_filebuf_out;
static QScopedPointer<std::filebuf> g_terminal_filebuf_err;
//Backup of original streams
static FILE g_terminal_backup_file_out;
static FILE g_terminal_backup_file_err;
static std::streambuf* g_terminal_backup_fbuf_out;
static std::streambuf* g_terminal_backup_fbuf_err;
//The log file
static QScopedPointer<QFile> g_terminal_log_file;
///////////////////////////////////////////////////////////////////////////////
// TERMINAL EXIT
///////////////////////////////////////////////////////////////////////////////
static void terminal_restore(void)
{
MUtils::Internal::CSLocker lock(g_terminal_lock);
if(g_terminal_attached)
{
RESTORE_STANDARD_STREAM(out);
RESTORE_STANDARD_STREAM(err);
FreeConsole();
g_terminal_attached = false;
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// TERMINAL SETUP // TERMINAL SETUP
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static bool g_terminal_attached = false; void MUtils::Terminal::setup(int &argc, char **argv, const char* const appName, const bool forceEnabled)
static QScopedPointer<std::filebuf> g_filebufStdOut;
static QScopedPointer<std::filebuf> g_filebufStdErr;
static QScopedPointer<QFile> g_log_file;
void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
{ {
MUtils::Internal::CSLocker lock(g_terminal_lock); MUtils::Internal::CSLocker lock(g_terminal_lock);
bool enableConsole = (MUTILS_DEBUG) || forceEnabled; bool enableConsole = (MUTILS_DEBUG) || forceEnabled;
@ -123,11 +183,11 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
{ {
if(logfile && (logfile_len > 0)) if(logfile && (logfile_len > 0))
{ {
g_log_file.reset(new QFile(MUTILS_QSTR(logfile))); g_terminal_log_file.reset(new QFile(MUTILS_QSTR(logfile)));
if(g_log_file->open(QIODevice::WriteOnly)) if(g_terminal_log_file->open(QIODevice::WriteOnly))
{ {
static const char MARKER[3] = { char(0xEF), char(0xBB), char(0xBF) }; static const char MARKER[3] = { char(0xEF), char(0xBB), char(0xBF) };
g_log_file->write(MARKER, 3); g_terminal_log_file->write(MARKER, 3);
} }
free(logfile); free(logfile);
} }
@ -155,9 +215,14 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
{ {
if(AllocConsole() != FALSE) if(AllocConsole() != FALSE)
{ {
SetConsoleCtrlHandler(NULL, TRUE);
SetConsoleTitle(L"LameXP - Audio Encoder Front-End | Debug Console");
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
SetConsoleCtrlHandler(NULL, TRUE);
if(appName && appName[0])
{
char title[128];
_snprintf_s(title, 128, _TRUNCATE, "%s | Debug Console", appName);
SetConsoleTitleA(title);
}
g_terminal_attached = true; g_terminal_attached = true;
} }
} }
@ -168,23 +233,9 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
//See: http://support.microsoft.com/default.aspx?scid=kb;en-us;105305 //See: http://support.microsoft.com/default.aspx?scid=kb;en-us;105305
//------------------------------------------------------------------- //-------------------------------------------------------------------
const int flags = _O_WRONLY | _O_U8TEXT; const int flags = _O_WRONLY | _O_U8TEXT;
const int hCrtStdOut = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE), flags); REPLACE_STANDARD_STREAM(out, STD_OUTPUT_HANDLE);
const int hCrtStdErr = _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE ), flags); REPLACE_STANDARD_STREAM(err, STD_ERROR_HANDLE );
FILE *const hfStdOut = (hCrtStdOut >= 0) ? _fdopen(hCrtStdOut, "wb") : NULL; atexit(terminal_restore);
FILE *const hfStdErr = (hCrtStdErr >= 0) ? _fdopen(hCrtStdErr, "wb") : NULL;
if(hfStdOut)
{
*stdout = *hfStdOut;
g_filebufStdOut.reset(new std::filebuf(hfStdOut));
std::cout.rdbuf(g_filebufStdOut.data());
}
if(hfStdErr)
{
*stderr = *hfStdErr;
g_filebufStdErr.reset(new std::filebuf(hfStdErr));
std::cerr.rdbuf(g_filebufStdErr.data());
std::cerr.rdbuf(new std::filebuf(hfStdErr));
}
const HWND hwndConsole = GetConsoleWindow(); const HWND hwndConsole = GetConsoleWindow();
if((hwndConsole != NULL) && (hwndConsole != INVALID_HANDLE_VALUE)) if((hwndConsole != NULL) && (hwndConsole != INVALID_HANDLE_VALUE))
@ -325,9 +376,9 @@ void MUtils::Terminal::write(const int &type, const char *const message)
write_debugger_helper(type, message); write_debugger_helper(type, message);
} }
if(!g_log_file.isNull()) if(!g_terminal_log_file.isNull())
{ {
write_logfile_helper(g_log_file.data(), type, message); write_logfile_helper(g_terminal_log_file.data(), type, message);
} }
} }