OSDN Git Service

Refactored the terminal initialization code. Also, we will now properly shut down...
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 21 Dec 2014 16:19:04 +0000 (17:19 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 21 Dec 2014 16:19:04 +0000 (17:19 +0100)
include/MUtils/Startup.h
include/MUtils/Terminal.h
src/Startup.cpp
src/Terminal_Win32.cpp

index ad7699c..e420982 100644 (file)
@@ -37,7 +37,7 @@ namespace MUtils
                typedef int (main_function_t)(int &argc, char **argv);
 
                //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
                MUTILS_API QApplication *create_qt(int &argc, char **argv, const QString &appName);
index e5039be..014296c 100644 (file)
@@ -34,7 +34,7 @@ namespace MUtils
        namespace 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
                MUTILS_API void write(const int &type, const char *const message);
index 50e7015..aaa82cd 100644 (file)
@@ -64,19 +64,19 @@ static bool qt_event_filter(void *message, long *result)
 // 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);
-       MUtils::Terminal::setup(argc, argv, MUTILS_DEBUG || debugConsole);
+       MUtils::Terminal::setup(argc, argv, appName, MUTILS_DEBUG || debugConsole);
        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;
        try
        {
-               iResult = startup_main(argc, argv, entry_point, debugConsole);
+               iResult = startup_main(argc, argv, entry_point, appName, debugConsole);
        }
        catch(const std::exception &error)
        {
@@ -91,21 +91,21 @@ static int startup_helper(int &argc, char **argv, MUtils::Startup::main_function
        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;
 #if (MUTILS_DEBUG)
 #ifdef _MSC_VER
        _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF || _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
 #endif //_MSCVER
-       iResult = startup_main(argc, argv, entry_point, debugConsole);
+       iResult = startup_main(argc, argv, entry_point, appName, debugConsole);
 #else //MUTILS_DEBUG
 #ifdef _MSC_VER
        __try
        {
                MUtils::ErrorHandler::initialize();
                MUtils::OS::check_debugger();
-               iResult = startup_helper(argc, argv, entry_point, debugConsole);
+               iResult = startup_helper(argc, argv, entry_point, appName, debugConsole);
        }
        __except(1)
        {
@@ -115,7 +115,7 @@ int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entr
 #else //_MSCVER
        MUtils::ErrorHandler::initialize();
        MUtils::OS::check_debugger();
-       iResult = startup_helper(argc, argv, entry_point, debugConsole);
+       iResult = startup_helper(argc, argv, entry_point, appName, debugConsole);
 #endif //_MSCVER
 #endif //MUTILS_DEBUG
        return iResult;
index 9f1b404..0dcc7f2 100644 (file)
@@ -45,9 +45,6 @@
 #include <fcntl.h>
 #include <ctime>
 
-//Lock
-static MUtils::Internal::CriticalSection g_terminal_lock;
-
 #ifdef _MSC_VER
 #define stricmp(X,Y) _stricmp((X),(Y))
 #endif
@@ -103,15 +100,78 @@ static const char *clean_str(char *str)
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// TERMINAL SETUP
+// HELPER MACROS
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool g_terminal_attached = false;
-static QScopedPointer<std::filebuf> g_filebufStdOut;
-static QScopedPointer<std::filebuf> g_filebufStdErr;
-static QScopedPointer<QFile> g_log_file;
+#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
+///////////////////////////////////////////////////////////////////////////////
 
-void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
+void MUtils::Terminal::setup(int &argc, char **argv, const char* const appName, const bool forceEnabled)
 {
        MUtils::Internal::CSLocker lock(g_terminal_lock);
        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))
                        {
-                               g_log_file.reset(new QFile(MUTILS_QSTR(logfile)));
-                               if(g_log_file->open(QIODevice::WriteOnly))
+                               g_terminal_log_file.reset(new QFile(MUTILS_QSTR(logfile)));
+                               if(g_terminal_log_file->open(QIODevice::WriteOnly))
                                {
                                        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);
                        }
@@ -155,9 +215,14 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled)
                {
                        if(AllocConsole() != FALSE)
                        {
-                               SetConsoleCtrlHandler(NULL, TRUE);
-                               SetConsoleTitle(L"LameXP - Audio Encoder Front-End | Debug Console");
                                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;
                        }
                }
@@ -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
                        //-------------------------------------------------------------------
                        const int flags = _O_WRONLY | _O_U8TEXT;
-                       const int hCrtStdOut = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE), flags);
-                       const int hCrtStdErr = _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE ), flags);
-                       FILE *const hfStdOut = (hCrtStdOut >= 0) ? _fdopen(hCrtStdOut, "wb") : NULL;
-                       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));
-                       }
+                       REPLACE_STANDARD_STREAM(out, STD_OUTPUT_HANDLE);
+                       REPLACE_STANDARD_STREAM(err, STD_ERROR_HANDLE );
+                       atexit(terminal_restore);
 
                        const HWND hwndConsole = GetConsoleWindow();
                        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);
        }
 
-       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);
        }
 }