Index: code/trunk/src/libraries/util/OutputHandler.h
===================================================================
--- code/trunk/src/libraries/util/OutputHandler.h	(revision 5738)
+++ code/trunk/src/libraries/util/OutputHandler.h	(revision 6105)
@@ -23,14 +23,12 @@
  *      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.
+@file
+@brief
+    Declaration of classes related to output (logging).
 */
 
@@ -40,166 +38,244 @@
 #include "UtilPrereqs.h"
 
-#include <iostream>
-#include <fstream>
+#include <list>
+#include <ostream>
 #include <string>
-
-#include "OutputBuffer.h"
+#include <vector>
+#include <utility>
 
 namespace orxonox
 {
-    //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
+    /**
+    @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
+        {
+            None    = 0,
+            Error   = 1,
+            Warning = 2,
+            Info    = 3,
+            Debug   = 4,
+            Verbose = 5,
+            Ultra   = 6,
+        };
+    }
+
+    // Forward declarations for classes in the source file
+    class LogFileWriter;
+    class ConsoleWriter;
+    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
-            };
-
-            static OutputHandler& getOutStream();
-
-            /** @brief Puts some text on the outstream. @param text The text */
+            //! Returns a reference to the only existing instance of the OutputHandler class.
+            static OutputHandler& getInstance();
+
+            //! Sets the output level and returns a stream to be used with "<<"
+            static inline OutputHandler& getOutStream(int level)
+                { return OutputHandler::getInstance().setOutputLevel(level); }
+
+            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; }
-
-            /** @brief Puts an error on the outstream. @param text The text */
+                { OutputHandler::getOutStream(0).output(text) << std::endl; return 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; }
-
-            /** @brief Puts a warning on the outstream. @param text The text */
+                { OutputHandler::getOutStream(1).output(text) << std::endl; return 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; }
-
-            /** @brief Puts an info on the outstream. @param text The text */
+                { OutputHandler::getOutStream(2).output(text) << std::endl; return 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; }
-
-            /** @brief Puts some debug output on the outstream. @param text The text */
+                { OutputHandler::getOutStream(3).output(text) << std::endl; return 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; }
-
-            /** @brief Returns a reference to the logfile. @return The logfile */
-            inline std::ofstream& getLogfile()
-                { return this->logfile_; }
-
-            /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
-            inline OutputBuffer* getOutputBuffer()
-                { return this->outputBuffer_; }
-
-            /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
+                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
+
+            //! 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);
+
+            //! Set the log path once the program has been properly initialised
+            void setLogPath(const std::string& path);
+            //! Disables the std::cout stream for output
+            void disableCout();
+            //! Enables the std::cout stream for output (startup behaviour)
+            void enableCout();
+
+            //! 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);
-
-            static void setLogPath(const std::string& path);
-
-            void setOutputBuffer(OutputBuffer* buffer);
-
+            //! 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   @remarks Only works for registered listeners!
+            void setSoftDebugLevel(const std::string& name, int level);
+
+            /**
+            @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);
-
-            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, redirects the output to the listeners
+            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
+
+            //! 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); }
+
+            //! 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();
-
-            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
+            OutputHandler();
+            ~OutputHandler();
+            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
+
+            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
+            ConsoleWriter*             consoleWriter_;    //!< Listener for std::cout (just program beginning)
+            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
+    @brief
+        Interface for listening to output.
+    @remarks
+        Remember to register the listener (not done automatically!)
     */
+    class OutputListener
+    {
+        friend class OutputHandler;
+
+    public:
+        OutputListener(const std::string& name)
+            : outputStream_(NULL)
+            , name_(name)
+            , softDebugLevel_(OutputLevel::Info)
+        {}
+        virtual ~OutputListener() {}
+
+        //! Gets called whenever output is put into the stream
+        virtual void outputChanged(int level) {}
+        //! Returns the name of this output listener
+        const std::string& getOutputListenerName() const { return this->name_; }
+        //! Returns the soft debug level of the listener
+        int getSoftDebugLevel() const { return this->softDebugLevel_; }
+        //! Sets the soft debug level of the listener
+        void setSoftDebugLevel(int level)
+        {
+            this->softDebugLevel_ = level;
+            OutputHandler::getInstance().setSoftDebugLevel(this->name_, level);
+        }
+
+    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
+    };
+
     template<class T>
-    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_)
+    inline OutputHandler& OutputHandler::output(const T& output)
+    {
+        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(this->outputLevel_);
+            }
         }
-
-        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
-    */
-    template<class T>
-    OutputHandler& operator<<(OutputHandler& out, const T& output)
-    {
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
-            std::cout << output;
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
-        {
-            out.getLogfile() << output;
-            out.getLogfile().flush();
-        }
-
-        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
-            (*out.getOutputBuffer()) << output;
-
-        return out;
-    }
 }
 
