[Orxonox-commit 1276] r5994 - in code/branches/console/src/libraries: core util

rgrieder at orxonox.net rgrieder at orxonox.net
Tue Oct 27 14:47:14 CET 2009


Author: rgrieder
Date: 2009-10-27 14:47:14 +0100 (Tue, 27 Oct 2009)
New Revision: 5994

Removed:
   code/branches/console/src/libraries/util/OutputBuffer.cc
   code/branches/console/src/libraries/util/OutputBuffer.h
Modified:
   code/branches/console/src/libraries/core/ConfigValueIncludes.h
   code/branches/console/src/libraries/core/Core.cc
   code/branches/console/src/libraries/core/Core.h
   code/branches/console/src/libraries/core/GUIManager.cc
   code/branches/console/src/libraries/core/GraphicsManager.cc
   code/branches/console/src/libraries/core/IOConsole.cc
   code/branches/console/src/libraries/core/LuaState.cc
   code/branches/console/src/libraries/core/Shell.cc
   code/branches/console/src/libraries/core/Shell.h
   code/branches/console/src/libraries/util/CMakeLists.txt
   code/branches/console/src/libraries/util/Debug.h
   code/branches/console/src/libraries/util/OrxAssert.h
   code/branches/console/src/libraries/util/OutputHandler.cc
   code/branches/console/src/libraries/util/OutputHandler.h
   code/branches/console/src/libraries/util/UtilPrereqs.h
Log:
Changed Output concept a little bit to allow for more general use.
Every output (log) target has to be implemented as OutputListener. There is already a LogFileWriter and a MemoryLogWriter (stores ALL the log in a vector and provides iterators).
The OutputListener has a unique and constant name, a stream pointer and a soft debug level (that can only be changed via OutputHandler::setSoftDebugLevel(name, level)).
This concept doesn't require the OutputBuffer anymore, so I deleted it.

The adjustments in the Shell are just preliminary for this commit.

Modified: code/branches/console/src/libraries/core/ConfigValueIncludes.h
===================================================================
--- code/branches/console/src/libraries/core/ConfigValueIncludes.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/ConfigValueIncludes.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -46,17 +46,17 @@
     @param varname The name of the variable
     @param defvalue The default-value of the variable
 */
-#define SetConfigValueGeneric(type, varname, defvalue) \
+#define SetConfigValueGeneric(type, varname, entryname, sectionname, defvalue) \
     static orxonox::Identifier* identifier##varname = this->getIdentifier(); \
     orxonox::ConfigValueContainer* container##varname = identifier##varname->getConfigValueContainer(#varname); \
     if (!container##varname) \
     { \
-        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
+        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, sectionname, entryname, defvalue, varname); \
         identifier##varname->addConfigValueContainer(#varname, container##varname); \
     } \
     container##varname->getValue(&varname, this)
 
-#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, defvalue)
+#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, identifier##varname->getName(), #varname, defvalue)
 
 
 /**

Modified: code/branches/console/src/libraries/core/Core.cc
===================================================================
--- code/branches/console/src/libraries/core/Core.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Core.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -105,24 +105,14 @@
         */
         void setConfigValues()
         {
-#ifdef NDEBUG
-            const unsigned int defaultLevelConsole = 1;
-            const unsigned int defaultLevelLogfile = 3;
-            const unsigned int defaultLevelShell   = 1;
+#ifdef ORXONOX_RELEASE
+            const unsigned int defaultLevelLogFile = 3;
 #else
-            const unsigned int defaultLevelConsole = 3;
-            const unsigned int defaultLevelLogfile = 4;
-            const unsigned int defaultLevelShell   = 3;
+            const unsigned int defaultLevelLogFile = 4;
 #endif
-            SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
-                .description("The maximal level of debug output shown in the console")
-                .callback(this, &CoreConfiguration::debugLevelChanged);
-            SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
-                .description("The maximal level of debug output shown in the logfile")
-                .callback(this, &CoreConfiguration::debugLevelChanged);
-            SetConfigValue(softDebugLevelShell_, defaultLevelShell)
-                .description("The maximal level of debug output shown in the ingame shell")
-                .callback(this, &CoreConfiguration::debugLevelChanged);
+            SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevelLogFile_, "softDebugLevelLogFile", "OutputHandler", defaultLevelLogFile)
+                .description("The maximum level of debug output shown in the log file");
+            OutputHandler::getInstance().setSoftDebugLevel(OutputHandler::logFileOutputListenerName_s, this->softDebugLevelLogFile_);
 
             SetConfigValue(language_, Language::getInstance().defaultLanguage_)
                 .description("The language of the in game text")
@@ -133,24 +123,6 @@
         }
 
         /**
-            @brief Callback function if the debug level has changed.
-        */
-        void debugLevelChanged()
-        {
-            // softDebugLevel_ is the maximum of the 3 variables
-            this->softDebugLevel_ = this->softDebugLevelConsole_;
-            if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
-                this->softDebugLevel_ = this->softDebugLevelLogfile_;
-            if (this->softDebugLevelShell_ > this->softDebugLevel_)
-                this->softDebugLevel_ = this->softDebugLevelShell_;
-
-            OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
-            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
-            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
-            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
-        }
-
-        /**
             @brief Callback function if the language has changed.
         */
         void languageChanged()
@@ -178,10 +150,7 @@
             }
         }
 
-        int softDebugLevel_;                            //!< The debug level
-        int softDebugLevelConsole_;                     //!< The debug level for the console
-        int softDebugLevelLogfile_;                     //!< The debug level for the logfile
-        int softDebugLevelShell_;                       //!< The debug level for the ingame shell
+        int softDebugLevelLogFile_;                     //!< The debug level for the log file (belongs to OutputHandler)
         std::string language_;                          //!< The language
         bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
     };
@@ -227,7 +196,7 @@
         this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
 
         // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% (Windows) was used
-        OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
+        OutputHandler::getInstance().setLogPath(PathConfig::getLogPathString());
 
         // Parse additional options file now that we know its path
         CommandLine::parseFile();
@@ -330,48 +299,6 @@
     }
 
     /**
-        @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
-        @param device The device
-        @return The softDebugLevel
-    */
-    /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
-    {
-        switch (device)
-        {
-        case OutputHandler::LD_All:
-            return Core::getInstance().configuration_->softDebugLevel_;
-        case OutputHandler::LD_Console:
-            return Core::getInstance().configuration_->softDebugLevelConsole_;
-        case OutputHandler::LD_Logfile:
-            return Core::getInstance().configuration_->softDebugLevelLogfile_;
-        case OutputHandler::LD_Shell:
-            return Core::getInstance().configuration_->softDebugLevelShell_;
-        default:
-            assert(0);
-            return 2;
-        }
-    }
-
-     /**
-        @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
-        @param device The device
-        @param level The level
-    */
-    /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
-    {
-        if (device == OutputHandler::LD_All)
-            Core::getInstance().configuration_->softDebugLevel_ = level;
-        else if (device == OutputHandler::LD_Console)
-            Core::getInstance().configuration_->softDebugLevelConsole_ = level;
-        else if (device == OutputHandler::LD_Logfile)
-            Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
-        else if (device == OutputHandler::LD_Shell)
-            Core::getInstance().configuration_->softDebugLevelShell_ = level;
-
-        OutputHandler::setSoftDebugLevel(device, level);
-    }
-
-    /**
         @brief Returns the configured language.
     */
     /*static*/ const std::string& Core::getLanguage()

Modified: code/branches/console/src/libraries/core/Core.h
===================================================================
--- code/branches/console/src/libraries/core/Core.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Core.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -68,8 +68,6 @@
 
             void setConfigValues();
 
-            static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
-            static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
             static const std::string& getLanguage();
             static void  resetLanguage();
 

Modified: code/branches/console/src/libraries/core/GUIManager.cc
===================================================================
--- code/branches/console/src/libraries/core/GUIManager.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/GUIManager.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -52,7 +52,6 @@
 #include "util/Debug.h"
 #include "util/Exception.h"
 #include "util/OrxAssert.h"
-#include "Core.h"
 #include "LuaState.h"
 #include "PathConfig.h"
 #include "Resource.h"
@@ -74,7 +73,7 @@
                 case CEGUI::Insane:      orxonoxLevel = 6; break;
                 default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
             }
-            OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
+            OutputHandler::getOutStream(orxonoxLevel)
                 << "CEGUI: " << message << std::endl;
 
             CEGUI::DefaultLogger::logEvent(message, level);
@@ -120,7 +119,7 @@
         ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
         // set the log level according to ours (translate by subtracting 1)
         ceguiLogger->setLoggingLevel(
-            static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
+            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
         this->ceguiLogger_ = ceguiLogger.release();
 
         // create the CEGUI system singleton

Modified: code/branches/console/src/libraries/core/GraphicsManager.cc
===================================================================
--- code/branches/console/src/libraries/core/GraphicsManager.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/GraphicsManager.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -407,7 +407,7 @@
         default:
             orxonoxLevel = 0;
         }
-        OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
+        OutputHandler::getOutStream(orxonoxLevel)
             << "Ogre: " << message << std::endl;
     }
 

Modified: code/branches/console/src/libraries/core/IOConsole.cc
===================================================================
--- code/branches/console/src/libraries/core/IOConsole.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/IOConsole.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -61,7 +61,7 @@
     {
         this->originalTerminalSettings_ = new termios;
         this->setTerminalMode();
-		this->shell_.registerListener(this);
+        this->shell_.registerListener(this);
     }
 
     IOConsole::~IOConsole()
@@ -233,6 +233,39 @@
         std::cout.flush();
     }
 
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+
+    IOConsole::IOConsole()
+        : shell_(Shell::getInstance())
+        , buffer_(Shell::getInstance().getInputBuffer())
+    {
+        this->setTerminalMode();
+    }
+
+    IOConsole::~IOConsole()
+    {
+    }
+
+    void IOConsole::setTerminalMode()
+    {
+    }
+
+    void IOConsole::resetTerminalMode()
+    {
+    }
+
+    void IOConsole::update(const Clock& time)
+    {
+    }
+
+    void IOConsole::print(const std::string& text)
+    {
+    }
+
+    void IOConsole::printInputLine()
+    {
+    }
+
 #endif /* ORXONOX_PLATFORM_UNIX */
 
     // ###############################
@@ -255,14 +288,14 @@
     */
     void IOConsole::onlyLastLineChanged()
     {
-		// Save cursor position and move it the beginning of the second to last line
-		std::cout << "\033[s\033[1F";
-		// Erase the second to last line
-		std::cout << "\033[K";
-		this->print(*(this->shell_.getNewestLineIterator()));
-		// Restore cursor
-		std::cout << "\033[u";
-		std::cout.flush();
+        // Save cursor position and move it the beginning of the second to last line
+        std::cout << "\033[s\033[1F";
+        // Erase the second to last line
+        std::cout << "\033[K";
+        this->print(*(this->shell_.getNewestLineIterator()));
+        // Restore cursor
+        std::cout << "\033[u";
+        std::cout.flush();
     }
 
     /**
@@ -271,11 +304,11 @@
     */
     void IOConsole::lineAdded()
     {
-		// Move curosr the beginning of the line and erase it
-		std::cout << "\033[1G\033[K";
-		this->print(*(this->shell_.getNewestLineIterator()));
-		std::cout << std::endl;
-		this->printInputLine();
+        // Move curosr the beginning of the line and erase it
+        std::cout << "\033[1G\033[K";
+        this->print(*(this->shell_.getNewestLineIterator()));
+        std::cout << std::endl;
+        this->printInputLine();
     }
 
     /**
@@ -302,11 +335,11 @@
     */
     void IOConsole::executed()
     {
-		// Move curosr the beginning of the line
-		std::cout << "\033[1G";
-        // Print command so the user knows what he typed
+        // Move cursor the beginning of the line
+        std::cout << "\033[1G";
+        // Print command so the user knows what he has typed
         std::cout << "orxonox>" << this->shell_.getInput() << std::endl;
-		this->printInputLine();
+        this->printInputLine();
     }
 
 

Modified: code/branches/console/src/libraries/core/LuaState.cc
===================================================================
--- code/branches/console/src/libraries/core/LuaState.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/LuaState.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -181,7 +181,7 @@
 
     void LuaState::luaLog(unsigned int level, const std::string& message)
     {
-        OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
+        OutputHandler::getOutStream(level) << message << std::endl;
     }
 
     bool LuaState::fileExists(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)

Modified: code/branches/console/src/libraries/core/Shell.cc
===================================================================
--- code/branches/console/src/libraries/core/Shell.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Shell.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -50,10 +50,8 @@
     Shell* Shell::singletonPtr_s = 0;
 
     Shell::Shell()
+        : OutputListener("shell")
     {
-        int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell);
-        Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
-
         RegisterRootObject(Shell);
 
         this->scrollPosition_ = 0;
@@ -68,32 +66,46 @@
         this->inputBuffer_ = new InputBuffer();
         this->configureInputBuffer();
 
-        this->outputBuffer_.registerListener(this);
-        OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);
-
         // Get a config file for the command history
         this->commandHistoryConfigFileType_ = ConfigFileManager::getInstance().getNewConfigFileType();
         ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini");
 
+        // Use a stringstream object to buffer the output and get it line by line in update()
+        this->outputStream_ = &this->outputBuffer_;
+
         this->setConfigValues();
 
-        Core::setSoftDebugLevel(OutputHandler::LD_Shell, level);
+        // Get the previous output and add it to the Shell
+        for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
+            it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
+            this->addLine(it->second, it->first);
+
+        // Register the shell as output listener
+        OutputHandler::getInstance().registerOutputListener(this);
     }
 
     Shell::~Shell()
     {
-        OutputHandler::getOutStream().setOutputBuffer(0);
-        if (this->inputBuffer_)
-            this->inputBuffer_->destroy();
+        OutputHandler::getInstance().unregisterOutputListener(this);
+        this->inputBuffer_->destroy();
     }
 
     void Shell::setConfigValues()
     {
-        SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
+        SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, "maxHistoryLength_", "Shell", 100)
             .callback(this, &Shell::commandHistoryLengthChanged);
-        SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
+        SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, "historyOffset_", "Shell", 0)
             .callback(this, &Shell::commandHistoryOffsetChanged);
         SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>());
+
+#ifdef ORXONOX_RELEASE
+        const unsigned int defaultLevel = 1;
+#else
+        const unsigned int defaultLevel = 3;
+#endif
+        SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevel_, "softDebugLevelShell", "OutputHandler", defaultLevel)
+            .description("The maximal level of debug output shown in the Shell");
+        OutputHandler::getInstance().setSoftDebugLevel("shell", this->softDebugLevel_);
     }
 
     void Shell::commandHistoryOffsetChanged()
@@ -181,14 +193,9 @@
 
     void Shell::addLine(const std::string& line, int level)
     {
-        int original_level = OutputHandler::getOutStream().getOutputLevel();
-        OutputHandler::getOutStream().setOutputLevel(level);
-
-        if (!this->finishedLastLine_)
-            this->outputBuffer_ << std::endl;
-
-        this->outputBuffer_ << line << std::endl;
-        OutputHandler::getOutStream().setOutputLevel(original_level);
+        if (level <= this->softDebugLevel_)
+            this->lines_.push_front(line);
+        this->updateListeners<&ShellListener::lineAdded>();
     }
 
     void Shell::clearLines()
@@ -237,17 +244,25 @@
         bool newline;
         do
         {
-            newline = this->outputBuffer_.getLine(&output);
+            std::getline(this->outputBuffer_, output);
 
+            bool eof = this->outputBuffer_.eof();
+            bool fail = this->outputBuffer_.fail();
+            if (eof)
+                this->outputBuffer_.flush();
+            if (eof || fail)
+                this->outputBuffer_.clear();
+            newline = (!eof && !fail);
+
             if (!newline && output == "")
                 break;
 
             if (this->finishedLastLine_)
             {
                 if (this->bAddOutputLevel_)
-                    output.insert(0, 1, static_cast<char>(OutputHandler::getOutStream().getOutputLevel()));
+                    output.insert(0, 1, static_cast<char>(OutputHandler::getInstance().getOutputLevel()));
 
-                this->lines_.insert(this->lines_.begin(), output);
+                this->lines_.push_front(output);
 
                 if (this->scrollPosition_)
                     this->scrollPosition_++;
@@ -364,14 +379,14 @@
         if (this->historyPosition_ == this->historyOffset_)
             return;
         unsigned int cursorPosition = this->getCursorPosition();
-        std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginning of the inputline untill the cursor position
-	for (unsigned int newPos = this->historyPosition_+1; newPos<=this->historyOffset_; newPos++)
+        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline untill the cursor position
+        for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
         {
-            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //search case insensitive
+            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
             {
                 this->historyPosition_ = newPos;
                 this->inputBuffer_->set(this->getFromHistory());
-                this->setCursorPosition( cursorPosition );
+                this->setCursorPosition(cursorPosition);
                 return;
             }
         }
@@ -382,14 +397,14 @@
         if (this->historyPosition_ == 0)
             return;
         unsigned int cursorPosition = this->getCursorPosition();
-        std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginn$
-        for (unsigned int newPos = this->historyPosition_-1; newPos>0; newPos--)
+        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginn$
+        for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
         {
-            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //sear$
+            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
             {
                 this->historyPosition_ = newPos;
                 this->inputBuffer_->set(this->getFromHistory());
-                this->setCursorPosition( cursorPosition );
+                this->setCursorPosition(cursorPosition);
                 return;
             }
         }

Modified: code/branches/console/src/libraries/core/Shell.h
===================================================================
--- code/branches/console/src/libraries/core/Shell.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/core/Shell.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -33,10 +33,11 @@
 
 #include <cassert>
 #include <list>
+#include <sstream>
 #include <string>
 #include <vector>
 
-#include "util/OutputBuffer.h"
+#include "util/OutputHandler.h"
 #include "input/InputBuffer.h"
 #include "OrxonoxClass.h"
 #include "ConfigFileManager.h"
@@ -60,7 +61,7 @@
             virtual void exit() {}
     };
 
-    class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputBufferListener
+    class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputListener
     {
         friend class Singleton<Shell>;
         public:
@@ -70,7 +71,7 @@
             static void clearShell();
             static void history();
 
-            virtual void setConfigValues();
+            void setConfigValues();
             void commandHistoryOffsetChanged();
             void commandHistoryLengthChanged();
 
@@ -79,8 +80,6 @@
 
             inline InputBuffer* getInputBuffer()
                 { return this->inputBuffer_; }
-            inline OutputBuffer& getOutputBuffer()
-                { return this->outputBuffer_; }
 
             void setCursorPosition(unsigned int cursor);
             inline unsigned int getCursorPosition() const
@@ -116,6 +115,7 @@
             std::string getFromHistory() const;
 
             virtual void outputChanged();
+
             void inputChanged();
             void execute();
             void hintandcomplete();
@@ -143,7 +143,7 @@
 
             std::list<ShellListener*> listeners_;
             InputBuffer* inputBuffer_;
-            OutputBuffer outputBuffer_;
+            std::stringstream outputBuffer_;
             bool finishedLastLine_;
             std::list<std::string> lines_;
             std::list<std::string>::const_iterator scrollIterator_;
@@ -153,6 +153,7 @@
             unsigned int historyPosition_;
             unsigned int historyOffset_;
             bool bAddOutputLevel_;
+            int softDebugLevel_;
 
             ConfigFileType commandHistoryConfigFileType_;
 

Modified: code/branches/console/src/libraries/util/CMakeLists.txt
===================================================================
--- code/branches/console/src/libraries/util/CMakeLists.txt	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/CMakeLists.txt	2009-10-27 13:47:14 UTC (rev 5994)
@@ -28,7 +28,6 @@
   Clock.cc
   CRC32.cc
   ExprParser.cc
-  OutputBuffer.cc
   OutputHandler.cc
   SignalHandler.cc
   Sleep.cc

Modified: code/branches/console/src/libraries/util/Debug.h
===================================================================
--- code/branches/console/src/libraries/util/Debug.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/Debug.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -75,9 +75,11 @@
 }
 
 /**
- at def COUT
+ at brief
     Logs text output: use exactly like std::cout, but specify an output
-    level as argument. For example COUT(3) << "Some info" << std::endl;
+    level as argument.
+ at example
+    COUT(3) << "Some info" << std::endl;
 @note
     The ? : operator requires both possible results to have the type of
     the first. This is achieved by the int conversion operator dummy

Modified: code/branches/console/src/libraries/util/OrxAssert.h
===================================================================
--- code/branches/console/src/libraries/util/OrxAssert.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OrxAssert.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -43,7 +43,7 @@
 // define an assert macro that can display a message
 #ifndef NDEBUG
 #define OrxAssert(Assertion, ErrorMessage) \
-    Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream().setOutputLevel(1) << ErrorMessage << std::endl); \
+    Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream(1) << ErrorMessage << std::endl); \
     assert(Assertion)
 #else
 #define OrxAssert(condition, errorMessage)  ((void)0)

Deleted: code/branches/console/src/libraries/util/OutputBuffer.cc
===================================================================
--- code/branches/console/src/libraries/util/OutputBuffer.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputBuffer.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -1,127 +0,0 @@
-/*
- *   ORXONOX - the hottest 3D action shooter ever to exist
- *                    > www.orxonox.net <
- *
- *
- *   License notice:
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation; either version 2
- *   of the License, or (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *   Author:
- *      Fabian 'x3n' Landau
- *   Co-authors:
- *      ...
- *
- */
-
-/**
-    @file
-    @brief Implementation of the OutputBuffer.
-*/
-
-#include "OutputBuffer.h"
-
-namespace orxonox
-{
-    /**
-        @brief Adds a new listener to the list.
-        @param listener The new listener
-    */
-    void OutputBuffer::registerListener(OutputBufferListener* listener)
-    {
-        this->listeners_.push_back(listener);
-    }
-
-    /**
-        @brief Removes a listener from the list.
-        @param listener The listener
-    */
-    void OutputBuffer::unregisterListener(OutputBufferListener* listener)
-    {
-        for (std::vector<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
-        {
-            if ((*it) == listener)
-                it = this->listeners_.erase(it);
-            else
-                ++it;
-        }
-    }
-
-    /**
-        @brief Puts a stream manipulator to the stream.
-        @param manipulator The manipulator
-    */
-    OutputBuffer& OutputBuffer::operator<<(std::ostream& (*manipulator)(std::ostream&))
-    {
-        this->stream_ << manipulator;
-        this->callListeners();
-        return *this;
-    }
-
-    /**
-        @brief Puts a stream manipulator to the stream.
-        @param manipulator The manipulator
-    */
-    OutputBuffer& OutputBuffer::operator<<(std::ios& (*manipulator)(std::ios&))
-    {
-        this->stream_ << manipulator;
-        this->callListeners();
-        return *this;
-    }
-
-    /**
-        @brief Puts a stream manipulator to the stream.
-        @param manipulator The manipulator
-    */
-    OutputBuffer& OutputBuffer::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
-    {
-        this->stream_ << manipulator;
-        this->callListeners();
-        return *this;
-    }
-
-    /**
-        @brief Removes the first line from the stream and assigns it to a given string object.
-        @param output The string object to assign the first line
-        @return True if there was at least one line in the stream and this line was successfully assigned
-
-        It's important to know the returned line will be removed from the stream. If there are more than one
-        listener, they have to cooperate to avoid conflicts.
-    */
-    bool OutputBuffer::getLine(std::string* output)
-    {
-        std::getline(this->stream_, *output);
-
-        bool eof = this->stream_.eof();
-        bool fail = this->stream_.fail();
-
-        if (eof)
-            this->stream_.flush();
-
-        if (eof || fail)
-            this->stream_.clear();
-
-        return (!eof && !fail);
-    }
-
-    /**
-        @brief Calls the outputChanged() function of all registered listeners.
-    */
-    void OutputBuffer::callListeners()
-    {
-        for (std::vector<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
-            (*it)->outputChanged();
-    }
-}

Deleted: code/branches/console/src/libraries/util/OutputBuffer.h
===================================================================
--- code/branches/console/src/libraries/util/OutputBuffer.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputBuffer.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -1,173 +0,0 @@
-/*
- *   ORXONOX - the hottest 3D action shooter ever to exist
- *                    > www.orxonox.net <
- *
- *
- *   License notice:
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation; either version 2
- *   of the License, or (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *   Author:
- *      Fabian 'x3n' Landau
- *   Co-authors:
- *      ...
- *
- */
-
-/**
-    @file
-    @brief Declaration of the OutputBuffer class.
-
-    The OutputBuffer acts almost like std::ostream. You can put text and other values to the
-    OutputBuffer by using the << operator. The OutputBuffer stores the text and calls registerd
-    listeners if new text gets assigned.
-    The listeners are then able to retrieve the text line by line.
-
-    It's important to know that getLine actually removes the line from the OutputBuffer, so it's
-    better to only have one "active" listener.
-*/
-
-#ifndef _OutputBuffer_H__
-#define _OutputBuffer_H__
-
-#include "UtilPrereqs.h"
-
-#include <vector>
-#include <sstream>
-
-namespace orxonox
-{
-    /**
-        @brief A pure virtual baseclass for classes that want to register as listener to an OutputBuffer.
-
-        This class is pure virtual, so an inheriting class has to implement the function on it's own.
-        The function get's called, if an instance of the inheriting class registers as a listener at
-        an OutputBuffer and this buffer changes.
-    */
-    class OutputBufferListener
-    {
-        friend class OutputBuffer;
-
-        public:
-            virtual ~OutputBufferListener() {}
-
-        private:
-            virtual void outputChanged() = 0;
-    };
-
-    /**
-        @brief The OutputBuffer acts almost like std::ostream and stores the assigned text.
-
-        If text gets assigned by using the << operator or another function, the OutputBuffer
-        calls it's listeners, allowing them to retrieve the text line by line.
-
-        It's important to know that getLine actually removes the line from the OutputBuffer, so it's
-        better to only have one "active" listener.
-    */
-    class _UtilExport OutputBuffer
-    {
-        public:
-            OutputBuffer() {}
-            ~OutputBuffer() {}
-
-            /**
-                @brief Puts some object/value to the OutputBuffer. The text gets assigned and the OutputBuffer calls it's listeners.
-                @param object The object/value to assign
-            */
-            template <class T>
-            inline OutputBuffer& operator<<(T object)
-            {
-                this->stream_ << object;
-                this->callListeners();
-                return *this;
-            }
-
-            /**
-                @brief Reads the stored text of the other OutputBuffer and calls the listeners.
-                @param object The other OutputBuffer
-            */
-            template <const OutputBuffer&>
-            inline OutputBuffer& operator<<(const OutputBuffer& object)
-            {
-                this->stream_ << object.stream_.rdbuf();
-                this->callListeners();
-                return *this;
-            }
-
-            OutputBuffer& operator<<(std::ostream& (*manipulator)(std::ostream&));
-            OutputBuffer& operator<<(std::ios& (*manipulator)(std::ios&));
-            OutputBuffer& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
-
-            /**
-                @brief Does the same like operator<<: Assigns the object to the stream and calls the listeners.
-                @param object The object/value
-            */
-            template <class T>
-            inline void add(T object)
-            {
-                this->stream_ << object;
-                this->callListeners();
-            }
-
-            /**
-                @brief Assigns an object/value and adds std::endl.
-                @param object The object/value
-            */
-            template <class T>
-            inline void addLine(T object)
-            {
-                this->stream_ << object << std::endl;
-                this->callListeners();
-            }
-
-            /**
-                @brief Puts std::endl to the stream and calls the listeners.
-            */
-            inline void newline()
-            {
-                this->stream_ << std::endl;
-                this->callListeners();
-            }
-
-            /**
-                @brief Flushes the stored text (~empties the OutputBuffer).
-            */
-            inline void flush()
-            {
-                this->stream_.flush();
-            }
-
-            bool getLine(std::string* output);
-
-            void registerListener(OutputBufferListener* listener);
-            void unregisterListener(OutputBufferListener* listener);
-
-            /**
-                @brief Returns the internal stringstream object.
-            */
-            inline std::stringstream& getStream()
-            {
-                return this->stream_;
-            }
-
-        private:
-            void callListeners();
-
-            std::stringstream stream_;                     //!< The stringstream that stores the assigned text
-            std::vector<OutputBufferListener*> listeners_; //!< A list of all listeners
-    };
-}
-
-#endif /* _OutputBuffer_H__ */

Modified: code/branches/console/src/libraries/util/OutputHandler.cc
===================================================================
--- code/branches/console/src/libraries/util/OutputHandler.cc	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputHandler.cc	2009-10-27 13:47:14 UTC (rev 5994)
@@ -22,210 +22,224 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Reto Grieder
  *
  */
 
 /**
-    @file
-    @brief Implementation of the OutputHandler class.
+ at file
+ at brief
+    Definition of classes related to output (logging).
 */
 
 #include "OutputHandler.h"
 
+#include <algorithm>
 #include <ctime>
 #include <cstdlib>
+#include <fstream>
+#include <sstream>
 
+#include "Debug.h"
+
 namespace orxonox
 {
+    //! How the log file shall be named on the filesystem
+    const std::string logFileBaseName_g = "orxonox.log";
+
+    /////////////////////////
+    ///// LogFileWriter /////
+    /////////////////////////
     /**
-        @brief Constructor: Opens the logfile and writes the first line.
-        @param logfilename The name of the logfile
+    @brief
+        Writes the output to the log file.
+    @note
+        As long as the correct log path is not yet known (for pre main code), the
+        LogFileWriter will write to a temporary file in /temp (Unix) or %TEMP% (Windows).
+        As soon as you set the correct path setLogPath the content of the temporary file
+        is read and put into the new file as well.
     */
-    OutputHandler::OutputHandler()
+    class LogFileWriter : public OutputListener
     {
+    public:
+        //! Gets temporary log path and starts the log file
+        LogFileWriter()
+            : OutputListener(OutputHandler::logFileOutputListenerName_s)
+        {
+            // Get path for a temporary file
 #ifdef ORXONOX_PLATFORM_WINDOWS
-        char* pTempDir = getenv("TEMP");
-        this->logfilename_ = std::string(pTempDir) + "/orxonox.log";
+            char* pTempDir = getenv("TEMP");
+            this->logFilename_ = std::string(pTempDir) + "/" + logFileBaseName_g;
 #else
-        this->logfilename_ = "/tmp/orxonox.log";
+            this->logFilename_ = std::string("/tmp/") + logFileBaseName_g;
 #endif
-#ifdef NDEBUG
-        this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 2;
-        this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 1;
-#else
-        this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 3;
-        this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 2;
-#endif
 
-        this->outputBuffer_ = &this->fallbackBuffer_;
-        this->logfile_.open(this->logfilename_.c_str(), std::fstream::out);
+            // Get current time
+            time_t rawtime;
+            struct tm* timeinfo;
+            time(&rawtime);
+            timeinfo = localtime(&rawtime);
 
-        time_t rawtime;
-        struct tm* timeinfo;
-        time(&rawtime);
-        timeinfo = localtime(&rawtime);
+            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
+            this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
+            this->logFile_.flush();
 
-        this->logfile_ << "Started log on " << asctime(timeinfo) << std::endl;
-        this->logfile_.flush();
-    }
+            this->outputStream_ = &this->logFile_;
+            // Use default level until we get the configValue from the Core
+            OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputLevel::Debug);
+            OutputHandler::getInstance().registerOutputListener(this);
+        }
 
+        //! Closes the log file
+        ~LogFileWriter()
+        {
+            this->logFile_ << "Closed log" << std::endl;
+            this->logFile_.close();
+        }
+
+        //! Changes the log path
+        void setLogPath(const std::string& path)
+        {
+            this->logFile_.close();
+            // Read old file into a buffer
+            std::ifstream old(this->logFilename_.c_str());
+            this->logFilename_ = path + logFileBaseName_g;
+            // Open the new file and feed it the content of the old one
+            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
+            this->logFile_ << old.rdbuf();
+            this->logFile_.flush();
+            old.close();
+        }
+
+    private:
+        std::ofstream logFile_;     //! File handle for the log file
+        std::string   logFilename_; //! Filename of the log file
+    };
+
+
+    ///////////////////////////
+    ///// MemoryLogWriter /////
+    ///////////////////////////
     /**
-        @brief Destructor: Writes the last line to the logfile and closes it.
+    @brief
+        OutputListener that writes all the output piece by piece to an array
+        associated with the corresponding output level.
+    @note
+        Only output below or equal to the current soft debug level is written
+        to minimise huge arrays for the normal run.
     */
-    OutputHandler::~OutputHandler()
+    class MemoryLogWriter : public OutputListener
     {
-        this->logfile_ << "Closed log" << std::endl;
-        this->logfile_.close();
-    }
+    public:
+        friend class OutputHandler;
 
-    /**
-        @brief Returns a reference to the only existing instance of the OutputHandler class.
-        @return The instance
-    */
-    OutputHandler& OutputHandler::getOutStream()
+        //! Sets the right soft debug level and registers itself
+        MemoryLogWriter()
+            : OutputListener("memoryLog")
+        {
+            this->outputStream_ = &this->buffer_;
+            // We capture as much input as the listener with the highest level
+            OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputHandler::getSoftDebugLevel());
+            OutputHandler::getInstance().registerOutputListener(this);
+        }
+
+        //! Pushed the just written output to the internal array
+        void outputChanged()
+        {
+            // Read ostringstream and store it
+            this->output_.push_back(std::make_pair(OutputHandler::getInstance().getOutputLevel(), this->buffer_.str()));
+            // Clear content and flags
+            this->buffer_.str(std::string());
+            this->buffer_.clear();
+        }
+
+    private:
+        std::ostringstream                        buffer_; //! Stream object used to process the output
+        std::vector<std::pair<int, std::string> > output_; //! Vector containing ALL output
+    };
+
+
+    /////////////////////////
+    ///// OutputHandler /////
+    /////////////////////////
+    const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
+          int         OutputHandler::softDebugLevel_s = hardDebugLevel;
+
+    //! Creates the LogFileWriter and the MemoryLogWriter
+    OutputHandler::OutputHandler()
+        : outputLevel_(OutputLevel::Verbose)
     {
-        static OutputHandler orxout;
-        return orxout;
+        this->logFile_ = new LogFileWriter();
+        this->output_  = new MemoryLogWriter();
     }
 
-    /**
-        @brief Sets the soft debug level for a given output device.
-        @param device The output device
-        @param level The debug level
-    */
-    void OutputHandler::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
+    //! Destroys the LogFileWriter and the MemoryLogWriter
+    OutputHandler::~OutputHandler()
     {
-        OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)] = level;
+        delete this->logFile_;
+        delete this->output_;
     }
 
-    /**
-        @brief Returns the soft debug level for a given output device.
-        @param device The output device
-        @return The debug level
-    */
-    int OutputHandler::getSoftDebugLevel(OutputHandler::OutputDevice device)
+    OutputHandler& OutputHandler::getInstance()
     {
-        return OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)];
+        static OutputHandler orxout;
+        return orxout;
     }
 
-    /**
-        @brief Sets the OutputBuffer, representing the third output stream.
-        @param buffer The OutputBuffer
-    */
-    void OutputHandler::setOutputBuffer(OutputBuffer* buffer)
+    void OutputHandler::registerOutputListener(OutputListener* listener)
     {
-        if (buffer == NULL)
-            this->outputBuffer_ = &this->fallbackBuffer_;
-        else
+        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
-            buffer->getStream() >> this->outputBuffer_->getStream().rdbuf();
-            this->outputBuffer_ = buffer;
+            if ((*it)->name_ == listener->name_)
+            {
+                COUT(2) << "OutputHandler, Warning: Trying to register two listeners with the same name!" << std::endl;
+                return;
+            }
         }
+        this->listeners_.push_back(listener);
     }
 
-    /**
-        @brief Sets the path where to create orxonox.log
-        @param Path string with trailing slash
-    */
+    void OutputHandler::unregisterOutputListener(OutputListener* listener)
+    {
+        this->listeners_.remove(listener);
+    }
+
     void OutputHandler::setLogPath(const std::string& path)
     {
-        OutputHandler::getOutStream().logfile_.close();
-        // store old content
-        std::ifstream old;
-        old.open(OutputHandler::getOutStream().logfilename_.c_str());
-        OutputHandler::getOutStream().logfilename_ = path + "orxonox.log";
-        OutputHandler::getOutStream().logfile_.open(OutputHandler::getOutStream().logfilename_.c_str(), std::fstream::out);
-        OutputHandler::getOutStream().logfile_ << old.rdbuf();
-        old.close();
-        OutputHandler::getOutStream().logfile_.flush();
+        this->logFile_->setLogPath(path);
     }
 
-    /**
-        @brief Overloaded << operator, redirects the output to the console and the logfile.
-        @param sb The streambuffer that should be shown in the console
-        @return A reference to the OutputHandler itself
-    */
-    OutputHandler& OutputHandler::operator<<(std::streambuf* sb)
+    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
     {
-        //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
-        //    std::cout << sb;
-
-        if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
-        {
-            this->logfile_ << sb;
-            this->logfile_.flush();
-        }
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
-            (*this->outputBuffer_) << sb;
-
-        return *this;
+        return this->output_->output_.begin();
     }
 
-    /**
-        @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
-        @param manipulator A function, manipulating the outstream.
-        @return A reference to the OutputHandler itself
-    */
-    OutputHandler& OutputHandler::operator<<(std::ostream& (*manipulator)(std::ostream&))
+    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
     {
-        //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
-        //    manipulator(std::cout);
-
-        if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
-        {
-            manipulator(this->logfile_);
-            this->logfile_.flush();
-        }
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
-            (*this->outputBuffer_) << manipulator;
-
-        return *this;
+        return this->output_->output_.end();
     }
 
-    /**
-        @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
-        @param manipulator A function, manipulating the outstream.
-        @return A reference to the OutputHandler itself
-    */
-    OutputHandler& OutputHandler::operator<<(std::ios& (*manipulator)(std::ios&))
+    int OutputHandler::getSoftDebugLevel(const std::string& name) const
     {
-        //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
-        //    manipulator(std::cout);
-
-        if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
-            manipulator(this->logfile_);
-            this->logfile_.flush();
+            if ((*it)->name_ == name)
+                return (*it)->softDebugLevel_;
         }
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
-            (*this->outputBuffer_) << manipulator;
-
-        return *this;
+        return -1;
     }
 
-    /**
-        @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
-        @param manipulator A function, manipulating the outstream.
-        @return A reference to the OutputHandler itself
-    */
-    OutputHandler& OutputHandler::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
+    void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
     {
-        //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
-        //    manipulator(std::cout);
-
-        if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+        int globalSoftDebugLevel = -1;
+        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
-            manipulator(this->logfile_);
-            this->logfile_.flush();
+            if ((*it)->name_ == name)
+                (*it)->softDebugLevel_ = level;
+            if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
+                globalSoftDebugLevel = (*it)->softDebugLevel_;
         }
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
-            (*this->outputBuffer_) << manipulator;
-
-        return *this;
+        // Update global soft debug level
+        OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
     }
 }

Modified: code/branches/console/src/libraries/util/OutputHandler.h
===================================================================
--- code/branches/console/src/libraries/util/OutputHandler.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/OutputHandler.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -22,16 +22,14 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Reto Grieder
  *
  */
 
 /**
-    @file
-    @brief Definition of the OutputHandler class.
-
-    The OutputHandler acts like std::cout, but output isn't only shown in the console,
-    but also written to the logfile and the ingame shell.
+ at file
+ at brief
+    Declaration of classes related to output (logging).
 */
 
 #ifndef _OutputHandler_H__
@@ -39,14 +37,26 @@
 
 #include "UtilPrereqs.h"
 
-#include <iostream>
-#include <fstream>
+#include <list>
+#include <ostream>
 #include <string>
+#include <vector>
+#include <utility>
 
-#include "OutputBuffer.h"
-
 namespace orxonox
 {
+    /**
+    @brief
+        Denotes different levels of text output (log output)
+
+        0, None   : Very important output
+        1, Error  : Errors
+        2, Warning: Warnings
+        3, Info   : Information
+        4, Debug  : Debug information
+        5, Verbose: More debug information
+        6, Ultra  : Crazy debug information
+    */
     namespace OutputLevel
     {
         enum Value
@@ -61,165 +71,197 @@
         };
     }
 
-    //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
+    // Forward declarations for classes in the source file
+    class LogFileWriter;
+    class MemoryLogWriter;
+
+    /**
+    @brief
+        The OutputHandler acts like std::cout, but output isn't only shown in the console.
+
+        You can register your own listener for output by inheriting from OutputListner.
+        And if you need the output previously processed, iterate over it with
+        OutputHandler::getOutputVector[Begin/End].
+        The way to output text is to first set the desired output level with
+        OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
+    */
     class _UtilExport OutputHandler
     {
         public:
-            enum OutputDevice
-            {
-                LD_All = 0,
-                LD_Console = 1,
-                LD_Logfile = 2,
-                LD_Shell = 3
-            };
+            //! Returns a reference to the only existing instance of the OutputHandler class.
+            static OutputHandler& getInstance();
 
-            static OutputHandler& getOutStream();
+            //! Sets the output level and returns a stream to be used with "<<"
             static inline OutputHandler& getOutStream(int level)
-                { return OutputHandler::getOutStream().setOutputLevel(level); }
+                { return OutputHandler::getInstance().setOutputLevel(level); }
 
-            /** @brief Puts some text on the outstream. @param text The text */
+            typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
+            //! Returns an iterator to the beginning of the all-output vector
+            OutputVectorIterator getOutputVectorBegin() const;
+            //! Returns an iterator to the end of the all-output vector
+            OutputVectorIterator getOutputVectorEnd() const;
+
+            //! Writes to all output devices
             static inline const std::string& log(const std::string& text)
-                { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
+                { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
 
-            /** @brief Puts an error on the outstream. @param text The text */
+            //! Writes an error message to the output
             static inline const std::string& error(const std::string& text)
-                { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
+                { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
 
-            /** @brief Puts a warning on the outstream. @param text The text */
+            //! Writes a warning message to the output
             static inline const std::string& warning(const std::string& text)
-                { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
+                { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
 
-            /** @brief Puts an info on the outstream. @param text The text */
+            //! Writes an informational message to the output
             static inline const std::string& info(const std::string& text)
-                { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
+                { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
 
-            /** @brief Puts some debug output on the outstream. @param text The text */
+            //! Writes a debug message to the output
             static inline const std::string& debug(const std::string& text)
-                { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
+                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
 
-            /** @brief Returns a reference to the logfile. @return The logfile */
-            inline std::ofstream& getLogfile()
-                { return this->logfile_; }
+            //! Registers an object that receives output via a provided std::ostream
+            void registerOutputListener(OutputListener* listener);
+            //! Unregisters an object that receives output via a provided std::ostream
+            void unregisterOutputListener(OutputListener* listener);
 
-            /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
-            inline OutputBuffer* getOutputBuffer()
-                { return this->outputBuffer_; }
+            //! Set the log path once the program has been properly initialised
+            void setLogPath(const std::string& path);
 
-            /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
+            //! Sets the level of the incoming output and returns the OutputHandler
             inline OutputHandler& setOutputLevel(int level)
                 { this->outputLevel_ = level; return *this; }
 
-            /** @brief Returns the level of the incoming output. @return The level */
+            //! Returns the level of the incoming output
             inline int getOutputLevel() const
                 { return this->outputLevel_; }
 
-            static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
-            static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
+            //! Returns the maximum debug level over all registered listeners (devices)
+            static int getSoftDebugLevel() { return softDebugLevel_s; }
+            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
+            int  getSoftDebugLevel(const std::string& name) const;
+            //! Sets the soft debug level for a listener by its name
+            void setSoftDebugLevel(const std::string& name, int level);
 
-            static void setLogPath(const std::string& path);
-
-            void setOutputBuffer(OutputBuffer* buffer);
-
+            /**
+            @brief
+                General template that copes with all output.
+                Required because operator << might be ambiguous.
+                @a output will be streamed into every listener with an appropriate debug level
+            @return
+                Returns a reference to the OutputHandler so you can use it again directly
+            */
             template <class T>
             OutputHandler& output(const T& output);
 
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(short val)              { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(int val)                { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(long val)               { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(long long val)          { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(float val)              { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(double val)             { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(long double val)        { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
-            /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
+            //! Overloaded << operator, redirects the output to the listeners
             inline OutputHandler& operator<<(bool val)               { return this->output(val); }
 
-            OutputHandler& operator<<(std::streambuf* sb);
+            //! Overloaded << operator, redirects the output to the listeners
+            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
 
-            OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
-            OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
-            OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
+            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
+            template <class T>
+            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
 
-            /** @brief Dummy operator required by Debug.h for the ternary operator */
-            inline operator int() { return 0; }
+            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
+            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
+            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
+            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
 
+            //! Dummy operator required by Debug.h for the ternary operator
+            inline operator int() const { return 0; }
+
+            //! Name of the OutputListener that writes to the log file
+            static const std::string logFileOutputListenerName_s;
+
         private:
-            explicit OutputHandler();
-            OutputHandler(const OutputHandler& oh);
-            virtual ~OutputHandler();
+            OutputHandler();
+            ~OutputHandler();
+            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
 
-            std::ofstream logfile_;              //!< The logfile where the output is logged
-            std::string logfilename_;            //!< The name of the logfile
-            OutputBuffer fallbackBuffer_;        //!< The OutputBuffer that gets used if there is no other OutputBuffer
-            OutputBuffer* outputBuffer_;         //!< The OutputBuffer to put output in (usually used by the Shell)
-            int outputLevel_;                    //!< The level of the incoming output
-            int softDebugLevel_[4];              //!< The soft debug level for each OutputDevice - the configurable maximal output level
+            std::list<OutputListener*> listeners_; //!< Array with all registered output listeners
+            int outputLevel_;                      //!< The level of the incoming output
+            LogFileWriter* logFile_;               //!< Listener that writes to the log file
+            MemoryLogWriter* output_;              //!< Listener that Stores ALL output below the current soft debug level
+            static int softDebugLevel_s;           //!< Maximum of all soft debug levels. @note This is only static for faster access
     };
 
-    /**
-        @brief Redirects the output to the console and the logfile.
-        @param output The value that should be shown in the console
-        @return A reference to the OutputHandler itself
-    */
     template<class T>
-    OutputHandler& OutputHandler::output(const T& output)
+    inline OutputHandler& OutputHandler::output(const T& output)
     {
-        //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
-        //    std::cout << output;
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
+        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
-            this->logfile_ << output;
-            this->logfile_.flush();
+            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
+            {
+                std::ostream& stream = *((*it)->outputStream_);
+                stream << output;
+                stream.flush();
+                (*it)->outputChanged();
+            }
         }
 
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
-            (*this->outputBuffer_) << output;
-
         return *this;
     }
 
     /**
-        @brief Overloading of the non-member << operator to redirect the output of classes with self defined '<< to std::ostream' operators to the console and the logfile.
-        @param out The OutputHandler itself
-        @param output The class that should be shown in the console
-        @return The OutputHandler itself
+    @brief
+        Interface for listening to output.
+    @remarks
+        Remember to register the listener (not done automatically!)
     */
-    template<class T>
-    OutputHandler& operator<<(OutputHandler& out, const T& output)
+    class OutputListener
     {
-        //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
-        //    std::cout << output;
+        friend class OutputHandler;
 
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
-        {
-            out.getLogfile() << output;
-            out.getLogfile().flush();
-        }
+    public:
+        OutputListener(const std::string& name)
+            : outputStream_(NULL)
+            , name_(name)
+        {}
+        virtual ~OutputListener() {}
 
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
-            (*out.getOutputBuffer()) << output;
+        //! Gets called whenever output is put into the stream
+        virtual void outputChanged() {}
+        //! Returns the name of this output listener
+        const std::string& getOutputListenerName() const { return this->name_; }
 
-        return out;
-    }
+    protected:
+        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
+
+    private:
+        const std::string name_;           //!< Name of the listener, constant and unique!
+        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
+    };
 }
 
 #endif /* _OutputHandler_H__ */

Modified: code/branches/console/src/libraries/util/UtilPrereqs.h
===================================================================
--- code/branches/console/src/libraries/util/UtilPrereqs.h	2009-10-26 22:01:39 UTC (rev 5993)
+++ code/branches/console/src/libraries/util/UtilPrereqs.h	2009-10-27 13:47:14 UTC (rev 5994)
@@ -86,9 +86,8 @@
     class IntVector2;
     class IntVector3;
     class MultiType;
-    class OutputBuffer;
-    class OutputBufferListener;
     class OutputHandler;
+    class OutputListener;
     template <ScopeID::Value>
     class Scope;
     template <class, ScopeID::Value>




More information about the Orxonox-commit mailing list