Index: code/trunk/src/libraries/core/command/Shell.cc
===================================================================
--- code/trunk/src/libraries/core/command/Shell.cc	(revision 8729)
+++ code/trunk/src/libraries/core/command/Shell.cc	(revision 8858)
@@ -35,7 +35,8 @@
 
 #include "util/Math.h"
-#include "util/OutputHandler.h"
 #include "util/StringUtils.h"
 #include "util/SubString.h"
+#include "util/output/OutputManager.h"
+#include "util/output/MemoryWriter.h"
 #include "core/CoreIncludes.h"
 #include "core/ConfigFileManager.h"
@@ -44,28 +45,28 @@
 #include "core/input/InputBuffer.h"
 #include "CommandExecutor.h"
-#include "ConsoleCommand.h"
 
 namespace orxonox
 {
-    SetConsoleCommand("log",     OutputHandler::log    );
-    SetConsoleCommand("error",   OutputHandler::error  ).hide();
-    SetConsoleCommand("warning", OutputHandler::warning).hide();
-    SetConsoleCommand("info",    OutputHandler::info   ).hide();
-    SetConsoleCommand("debug",   OutputHandler::debug  ).hide();
-
     unsigned int Shell::cacheSize_s;
 
-    /**
-        @brief Constructor: Initializes the values and registers itself at OutputHandler.
+    namespace DefaultLogLevel
+    {
+        const OutputLevel Dev  = level::internal_warning;
+        const OutputLevel User = level::user_info;
+    }
+
+    /**
+        @brief Constructor: Initializes the values.
         @param consoleName The name of the shell - used to define the name of the soft-debug-level config-value
         @param bScrollable If true, the user is allowed to scroll through the output-lines
     */
     Shell::Shell(const std::string& consoleName, bool bScrollable)
-        : OutputListener(consoleName)
+        : BaseWriter(consoleName, false)
         , inputBuffer_(new InputBuffer())
-        , consoleName_(consoleName)
         , bScrollable_(bScrollable)
     {
         RegisterRootObject(Shell);
+
+        OutputManager::getInstance().registerListener(this);
 
         this->scrollPosition_ = 0;
@@ -73,5 +74,4 @@
         this->historyPosition_ = 0;
         this->historyOffset_ = 0;
-        this->bFinishedLastLine_ = true;
 
         this->clearOutput();
@@ -81,38 +81,22 @@
         ConfigFileManager::getInstance().setFilename(ConfigFileType::CommandHistory, "commandHistory.ini");
 
-        // Use a stringstream object to buffer the output
-        this->outputStream_ = &this->outputBuffer_;
+        // Choose the default level according to the path Orxonox was started (build directory or not)
+        OutputLevel defaultDebugLevel = (PathConfig::buildDirectoryRun() ? DefaultLogLevel::Dev : DefaultLogLevel::User);
+        this->setLevelMax(defaultDebugLevel);
 
         this->setConfigValues();
 
         // Get the previous output and add it to the Shell
-        OutputHandler::OutputVector::const_iterator it = OutputHandler::getInstance().getOutput().begin();
-        for (;it != OutputHandler::getInstance().getOutput().end(); ++it)
-        {
-            if (it->first <= debugLevel_)
-            {
-                this->outputBuffer_ << it->second;
-                this->outputChanged(it->first);
-            }
-        }
-
-        // Register the shell as output listener
-        OutputHandler::getInstance().registerOutputListener(this);
-        OutputHandler::getInstance().setSoftDebugLevel(consoleName_, debugLevel_);
-    }
-
-    /**
-        @brief Destructor: Unregisters the shell from OutputHandler.
+        MemoryWriter::getInstance().resendOutput(this);
+    }
+
+    /**
+        @brief Destructor
     */
     Shell::~Shell()
     {
-        OutputHandler::getInstance().unregisterOutputListener(this);
         this->inputBuffer_->destroy();
-    }
-
-    namespace DefaultLogLevel
-    {
-        const OutputLevel::Value Dev  = OutputLevel::Info;
-        const OutputLevel::Value User = OutputLevel::Error;
+
+        OutputManager::getInstance().unregisterListener(this);
     }
 
@@ -129,9 +113,22 @@
         SetConfigValue(cacheSize_s, 32);
 
-        // Choose the default level according to the path Orxonox was started (build directory or not)
-        OutputLevel::Value defaultDebugLevel = (PathConfig::buildDirectoryRun() ? DefaultLogLevel::Dev : DefaultLogLevel::User);
-        SetConfigValueExternal(debugLevel_, "OutputHandler", "debugLevel" + consoleName_, defaultDebugLevel)
-            .description("The maximum level of debug output shown in the " + consoleName_);
-        OutputHandler::getInstance().setSoftDebugLevel(consoleName_, debugLevel_);
+        SetConfigValueExternal(this->configurableMaxLevel_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableMaxLevelName(),
+                               this->configurableMaxLevel_)
+            .description("The maximum level of output shown in the " + this->getName())
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableLevel);
+        SetConfigValueExternal(this->configurableAdditionalContextsMaxLevel_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableAdditionalContextsMaxLevelName(),
+                               this->configurableAdditionalContextsMaxLevel_)
+            .description("The maximum level of output shown in the " + this->getName() + " for additional contexts")
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableAdditionalContextsLevel);
+        SetConfigValueExternal(this->configurableAdditionalContexts_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableAdditionalContextsName(),
+                               this->configurableAdditionalContexts_)
+            .description("Additional output contexts shown in the " + this->getName())
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableAdditionalContexts);
     }
 
@@ -168,10 +165,10 @@
         if (isNormal)
         {
-            ModifyConfigValueExternal(debugLevel_, "debugLevel" + consoleName_, update);
+            ModifyConfigValueExternal(this->configurableMaxLevel_, this->getConfigurableMaxLevelName(), update);
         }
         else
         {
-            OutputLevel::Value level = (value ? DefaultLogLevel::Dev : DefaultLogLevel::User);
-            ModifyConfigValueExternal(debugLevel_, "debugLevel" + consoleName_, tset, level);
+            OutputLevel level = (value ? DefaultLogLevel::Dev : DefaultLogLevel::User);
+            ModifyConfigValueExternal(this->configurableMaxLevel_, this->getConfigurableMaxLevelName(), tset, level);
         }
     }
@@ -252,10 +249,31 @@
 
     /**
-        @brief Sends output to the internal output buffer.
+        @brief Adds multiple lines to the internal output buffer.
     */
     void Shell::addOutput(const std::string& text, LineType type)
     {
-        this->outputBuffer_ << text;
-        this->outputChanged(type);
+        std::vector<std::string> lines;
+        vectorize(text, '\n', &lines);
+
+        for (size_t i = 0; i < lines.size(); ++i)
+            this->addLine(lines[i], type);
+    }
+
+    /**
+        @brief Adds a line to the internal output buffer.
+    */
+    void Shell::addLine(const std::string& line, LineType type)
+    {
+        // yes it was - push the new line to the list
+        this->outputLines_.push_front(std::make_pair(line, static_cast<LineType>(type)));
+
+        // adjust the scroll position if needed
+        if (this->scrollPosition_)
+            this->scrollPosition_++;
+        else
+            this->scrollIterator_ = this->outputLines_.begin();
+
+        if (!this->scrollPosition_)
+            this->updateListeners<&ShellListener::lineAdded>();
     }
 
@@ -269,7 +287,14 @@
 
         this->scrollPosition_ = 0;
-        this->bFinishedLastLine_ = true;
 
         this->updateListeners<&ShellListener::linesChanged>();
+    }
+
+    /**
+        @brief Inherited from BaseWriter (LogListener), called if a new line of output was sent.
+    */
+    void Shell::printLine(const std::string& line, OutputLevel level)
+    {
+        this->addLine(line, static_cast<LineType>(level));
     }
 
@@ -323,59 +348,4 @@
 
     /**
-        @brief Called by OutputHandler or internally whenever output was sent to the output buffer. Reads from the buffer and writes the new output-lines to the list.
-    */
-    void Shell::outputChanged(int lineType)
-    {
-        bool newline = false;
-        do
-        {
-            // get the first line from the buffer
-            std::string output;
-            std::getline(this->outputBuffer_, output);
-
-            // check the state of the buffer
-            bool eof = this->outputBuffer_.eof();
-            bool fail = this->outputBuffer_.fail();
-            if (eof)
-                this->outputBuffer_.flush(); // check if more output was received in the meantime
-            if (eof || fail)
-                this->outputBuffer_.clear(); // clear the error flags
-
-            // the line is terminated with a line-break if neither an error occurred nor the end of the file was reached
-            newline = (!eof && !fail);
-
-            // no output retrieved - break the loop
-            if (!newline && output.empty())
-                break;
-
-            // check if the last line was terminated with a line-break
-            if (this->bFinishedLastLine_)
-            {
-                // yes it was - push the new line to the list
-                this->outputLines_.push_front(std::make_pair(output, static_cast<LineType>(lineType)));
-
-                // adjust the scroll position if needed
-                if (this->scrollPosition_)
-                    this->scrollPosition_++;
-                else
-                    this->scrollIterator_ = this->outputLines_.begin();
-
-                if (!this->scrollPosition_)
-                    this->updateListeners<&ShellListener::lineAdded>();
-            }
-            else
-            {
-                // no it wasn't - add the new output to the last line
-                this->outputLines_.front().first += output;
-                this->updateListeners<&ShellListener::onlyLastLineChanged>();
-            }
-
-            // remember if the last line was terminated with a line-break
-            this->bFinishedLastLine_ = newline;
-
-        } while (newline); // loop as long as more lines are in the buffer
-    }
-
-    /**
         @brief Clears the text in the input buffer.
     */
@@ -409,19 +379,7 @@
         const std::string& result = CommandExecutor::query(this->inputBuffer_->get(), &error);
         if (error)
-        {
-            switch (error)
-            {
-                case CommandExecutor::Error:       this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\", command doesn't exist. (S)" << std::endl; break;
-                case CommandExecutor::Incomplete:  this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\", not enough arguments given. (S)" << std::endl; break;
-                case CommandExecutor::Deactivated: this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\", command is not active. (S)" << std::endl; break;
-                case CommandExecutor::Denied:      this->outputBuffer_ << "Error: Can't execute \"" << this->inputBuffer_->get() << "\", access denied. (S)" << std::endl; break;
-            }
-            this->outputChanged(Error);
-        }
+            this->addOutput("Error: Can't execute \"" + this->inputBuffer_->get() + "\", " + CommandExecutor::getErrorDescription(error) + ". (Shell)", UserError);
         else if (result != "")
-        {
-            this->outputBuffer_ << result << std::endl;
-            this->outputChanged(Command);
-        }
+            this->addOutput(result, Result);
 
         this->clearInput();
@@ -432,6 +390,5 @@
     {
         this->inputBuffer_->set(CommandExecutor::evaluate(this->inputBuffer_->get()).complete());
-        this->outputBuffer_ << CommandExecutor::evaluate(this->inputBuffer_->get()).hint() << std::endl;
-        this->outputChanged(Hint);
+        this->addOutput(CommandExecutor::evaluate(this->inputBuffer_->get()).hint(), Hint);
 
         this->inputChanged();
