Index: code/branches/network/src/orxonox/console/InGameConsole.cc
===================================================================
--- code/branches/network/src/orxonox/console/InGameConsole.cc	(revision 1371)
+++ code/branches/network/src/orxonox/console/InGameConsole.cc	(revision 1446)
@@ -23,5 +23,5 @@
  *      Felix Schulthess
  *   Co-authors:
- *      ...
+ *      Fabian 'x3n' Landau
  *
  */
@@ -40,243 +40,464 @@
 #include "core/Debug.h"
 #include "core/CoreIncludes.h"
+#include "core/ConfigValueIncludes.h"
 #include "core/ConsoleCommand.h"
 #include "core/InputManager.h"
+#include "util/Math.h"
 #include "GraphicsEngine.h"
 
-#define LINES 20
+#define LINES 30
+#define CHAR_WIDTH 7.85 // fix this please - determine the char-width dynamically
 
 namespace orxonox
 {
+    SetConsoleCommand(InGameConsole, openConsole, true);
+    SetConsoleCommand(InGameConsole, closeConsole, true);
+
     using namespace Ogre;
 
-    const float REL_WIDTH = 0.8;
-    const float REL_HEIGHT = 0.4;
-    const float BLINK = 0.25;
-
-    InGameConsole::InGameConsole(InputBuffer* ib) :
-        windowW(0), windowH(0),
-        scroll(0), scrollTimer(0.0f),
-        cursor(0.0f),
-        active(false),
-        ib_(ib),
-        om(0),
-        consoleOverlay(0),
-        consoleOverlayContainer(0),
-        consoleOverlayNoise(0),
-        consoleOverlayBorder(0),
-        consoleOverlayTextAreas(0)
-    {
-        //RegisterObject(InGameConsole);
-        init();
-    }
-
-    InGameConsole::~InGameConsole(void){
-        for(int i=0; i<LINES; i++) delete consoleOverlayTextAreas[i];
-        delete consoleOverlayTextAreas;
-    }
-
-    void InGameConsole::listen(){
-        if(!active) activate();
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::execute(){	
-        newline();
-        if (!CommandExecutor::execute(this->ib_->get())){
-            print("Error");
-            newline();
-        }
-        this->ib_->clear();
-    }
-
-    void InGameConsole::hintandcomplete(){
-        print(CommandExecutor::hint(this->ib_->get()));
-        newline();
-        this->ib_->set(CommandExecutor::complete(this->ib_->get()));
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::clear(){
-        this->ib_->clear();
-    }
-
-    void InGameConsole::removeLast(){
-        this->ib_->removeLast();
-    }
-
-    void InGameConsole::exit(){
-        clear();
-        deactivate();
-        InputManager::setInputState(InputManager::IS_NORMAL);
-    }
-
-    /**
-    @brief called once by constructor
-    */
-    void InGameConsole::init(){
+    float InGameConsole::REL_WIDTH = 0.8;
+    float InGameConsole::REL_HEIGHT = 0.4;
+    float InGameConsole::BLINK = 0.5;
+
+    /**
+        @brief Constructor: Creates and initializes the InGameConsole.
+    */
+    InGameConsole::InGameConsole() :
+        om_(0), consoleOverlay_(0), consoleOverlayContainer_(0),
+        consoleOverlayNoise_(0), consoleOverlayBorder_(0), consoleOverlayTextAreas_(0)
+    {
+        RegisterObject(InGameConsole);
+
+        this->active_ = false;
+        this->cursor_ = 0.0;
+        this->cursorSymbol_ = '|';
+        this->inputWindowStart_ = 0;
+        this->numLinesShifted_ = LINES - 1;
+
+        this->init();
+        this->setConfigValues();
+
+        Shell::getInstance().addOutputLevel(true);
+    }
+
+    /**
+        @brief Destructor: Destroys the TextAreas.
+    */
+    InGameConsole::~InGameConsole(void)
+    {
+        for (int i = 0; i < LINES; i++)
+            if (this->consoleOverlayTextAreas_[i])
+                delete this->consoleOverlayTextAreas_[i];
+
+        if (this->consoleOverlayTextAreas_)
+            delete this->consoleOverlayTextAreas_;
+    }
+
+    /**
+        @brief Returns a reference to the only existing instance of InGameConsole.
+    */
+    InGameConsole& InGameConsole::getInstance()
+    {
+        static InGameConsole instance;
+        return instance;
+    }
+
+    /**
+        @brief Sets the config values, describing the size of the console.
+    */
+    void InGameConsole::setConfigValues()
+    {
+        SetConfigValue(REL_WIDTH, 0.8);
+        SetConfigValue(REL_HEIGHT, 0.4);
+        SetConfigValue(BLINK, 0.5);
+    }
+
+    /**
+        @brief Called if all output-lines have to be redrawn.
+    */
+    void InGameConsole::linesChanged()
+    {
+        std::list<std::string>::const_iterator it = Shell::getInstance().getNewestLineIterator();
+        int max = 0;
+        for (int i = 1; i < LINES; ++i)
+        {
+            if (it != Shell::getInstance().getEndIterator())
+            {
+                ++it;
+                max = i;
+            }
+            else
+                break;
+        }
+
+        for (int i = LINES - 1; i > max; --i)
+            this->print("", i, true);
+
+        for (int i = max; i >= 1; --i)
+        {
+            --it;
+            this->print(*it, i, true);
+        }
+    }
+
+    /**
+        @brief Called if only the last output-line has changed.
+    */
+    void InGameConsole::onlyLastLineChanged()
+    {
+        if (LINES > 1)
+            this->print(*Shell::getInstance().getNewestLineIterator(), 1);
+    }
+
+    /**
+        @brief Called if a new output-line was added.
+    */
+    void InGameConsole::lineAdded()
+    {
+        this->numLinesShifted_ = 0;
+        this->shiftLines();
+        this->onlyLastLineChanged();
+    }
+
+    /**
+        @brief Called if the text in the input-line has changed.
+    */
+    void InGameConsole::inputChanged()
+    {
+        if (LINES > 0)
+            this->print(Shell::getInstance().getInput(), 0);
+
+        if (Shell::getInstance().getInput() == "" || Shell::getInstance().getInput().size() == 0)
+            this->inputWindowStart_ = 0;
+    }
+
+    /**
+        @brief Called if the position of the cursor in the input-line has changed.
+    */
+    void InGameConsole::cursorChanged()
+    {
+        std::string input = Shell::getInstance().getInput();
+        input.insert(Shell::getInstance().getCursorPosition(), 1, this->cursorSymbol_);
+        if (LINES > 0)
+            this->print(input, 0);
+    }
+
+    /**
+        @brief Called if the console gets closed.
+    */
+    void InGameConsole::exit()
+    {
+        this->deactivate();
+    }
+
+    /**
+        @brief Called once by constructor, initializes the InGameConsole.
+    */
+    void InGameConsole::init()
+    {
         // for the beginning, don't scroll
-        scroll = 0;
-        scrollTimer = 0;
-        cursor = 0;
+        this->scroll_ = 0;
+        this->scrollTimer_ = 0;
+        this->cursor_ = 0;
 
         // create overlay and elements
-        om = &Ogre::OverlayManager::getSingleton();
+        this->om_ = &Ogre::OverlayManager::getSingleton();
 
         // create a container
-        consoleOverlayContainer = static_cast<OverlayContainer*>(om->createOverlayElement("Panel", "container"));
-        consoleOverlayContainer->setMetricsMode(Ogre::GMM_RELATIVE);
-        consoleOverlayContainer->setPosition((1-REL_WIDTH)/2, 0);
-        consoleOverlayContainer->setDimensions(REL_WIDTH, REL_HEIGHT);
+        this->consoleOverlayContainer_ = static_cast<OverlayContainer*>(this->om_->createOverlayElement("Panel", "InGameConsoleContainer"));
+        this->consoleOverlayContainer_->setMetricsMode(Ogre::GMM_RELATIVE);
+        this->consoleOverlayContainer_->setPosition((1 - InGameConsole::REL_WIDTH) / 2, 0);
+        this->consoleOverlayContainer_->setDimensions(InGameConsole::REL_WIDTH, InGameConsole::REL_HEIGHT);
 
         // create BorderPanel
-        consoleOverlayBorder = static_cast<BorderPanelOverlayElement*>(om->createOverlayElement("BorderPanel", "borderPanel"));
-        consoleOverlayBorder->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayBorder->setMaterialName("ConsoleCenter");
+        this->consoleOverlayBorder_ = static_cast<BorderPanelOverlayElement*>(this->om_->createOverlayElement("BorderPanel", "InGameConsoleBorderPanel"));
+        this->consoleOverlayBorder_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayBorder_->setMaterialName("ConsoleCenter");
         // set parameters for border
-        consoleOverlayBorder->setBorderSize(16, 16, 0, 16);
-        consoleOverlayBorder->setBorderMaterialName("ConsoleBorder");
-        consoleOverlayBorder->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
-        consoleOverlayBorder->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
-        consoleOverlayBorder->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
-        consoleOverlayBorder->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
-        consoleOverlayBorder->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
+        this->consoleOverlayBorder_->setBorderSize(16, 16, 0, 16);
+        this->consoleOverlayBorder_->setBorderMaterialName("ConsoleBorder");
+        this->consoleOverlayBorder_->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
+        this->consoleOverlayBorder_->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
+        this->consoleOverlayBorder_->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
+        this->consoleOverlayBorder_->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
+        this->consoleOverlayBorder_->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
 
         // create the text lines
-        consoleOverlayTextAreas = new TextAreaOverlayElement*[LINES];
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i] = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "textArea"+Ogre::StringConverter::toString(i)));
-            consoleOverlayTextAreas[i]->setMetricsMode(Ogre::GMM_PIXELS);
-            consoleOverlayTextAreas[i]->setFontName("Console");
-            consoleOverlayTextAreas[i]->setCharHeight(20);
-            consoleOverlayTextAreas[i]->setParameter("colour_top", "0.21 0.69 0.21");
-            consoleOverlayTextAreas[i]->setLeft(8);
-            consoleOverlayTextAreas[i]->setCaption("");
+        this->consoleOverlayTextAreas_ = new TextAreaOverlayElement*[LINES];
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i] = static_cast<TextAreaOverlayElement*>(this->om_->createOverlayElement("TextArea", "InGameConsoleTextArea" + Ogre::StringConverter::toString(i)));
+            this->consoleOverlayTextAreas_[i]->setMetricsMode(Ogre::GMM_PIXELS);
+            this->consoleOverlayTextAreas_[i]->setFontName("Console");
+            this->consoleOverlayTextAreas_[i]->setCharHeight(18);
+            this->consoleOverlayTextAreas_[i]->setParameter("colour_top", "0.21 0.69 0.21");
+            this->consoleOverlayTextAreas_[i]->setLeft(8);
+            this->consoleOverlayTextAreas_[i]->setCaption("");
         }
 
         // create noise
-        consoleOverlayNoise = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel", "noise"));
-        consoleOverlayNoise->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayNoise->setPosition(5,0);
-        consoleOverlayNoise->setMaterialName("ConsoleNoise");
-
-        consoleOverlay = om->create("Console");
-        consoleOverlay->add2D(consoleOverlayContainer);
-        consoleOverlayContainer->addChild(consoleOverlayBorder);
-//comment following line to disable noise
-        consoleOverlayContainer->addChild(consoleOverlayNoise);
-        for(int i = 0; i<LINES; i++) consoleOverlayContainer->addChild(consoleOverlayTextAreas[i]);
-        resize();
+        this->consoleOverlayNoise_ = static_cast<PanelOverlayElement*>(this->om_->createOverlayElement("Panel", "InGameConsoleNoise"));
+        this->consoleOverlayNoise_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayNoise_->setPosition(5,0);
+        this->consoleOverlayNoise_->setMaterialName("ConsoleNoise");
+
+        this->consoleOverlay_ = this->om_->create("InGameConsoleConsole");
+        this->consoleOverlay_->add2D(this->consoleOverlayContainer_);
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayBorder_);
+        //comment following line to disable noise
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayNoise_);
+        for (int i = 0; i < LINES; i++)
+            this->consoleOverlayContainer_->addChild(this->consoleOverlayTextAreas_[i]);
+
+        this->resize();
 
         // move overlay "above" the top edge of the screen
         // we take -1.2 because the border mkes the panel bigger
-        consoleOverlayContainer->setTop(-1.2*REL_HEIGHT);
+        this->consoleOverlayContainer_->setTop(-1.2 * InGameConsole::REL_HEIGHT);
         // show overlay
-        consoleOverlay->show();
-
-        COUT(3) << "Info: InGameConsole initialized" << std::endl;
-    }
-
-    /**
-    @brief used to control the actual scrolling and cursor
-    */
-    void InGameConsole::tick(float dt){
-        scrollTimer += dt;
-        if(scrollTimer >= 0.01){
-            float top = consoleOverlayContainer->getTop();
-            scrollTimer = 0;
-            if(scroll!=0){
+        this->consoleOverlay_->show();
+
+        COUT(4) << "Info: InGameConsole initialized" << std::endl;
+    }
+
+    /**
+        @brief Resizes the console elements. Call if window size changes.
+    */
+    void InGameConsole::resize()
+    {
+        this->windowW_ = GraphicsEngine::getSingleton().getWindowWidth();
+        this->windowH_ = GraphicsEngine::getSingleton().getWindowHeight();
+        this->consoleOverlayBorder_->setWidth((int) this->windowW_* InGameConsole::REL_WIDTH);
+        this->consoleOverlayBorder_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT);
+        this->consoleOverlayNoise_->setWidth((int) this->windowW_ * InGameConsole::REL_WIDTH - 10);
+        this->consoleOverlayNoise_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT - 5);
+
+        // now adjust the text lines...
+        this->desiredTextWidth_ = (int) (this->windowW_ * InGameConsole::REL_WIDTH) - 12;
+
+        if (LINES > 0)
+            this->maxCharsPerLine_ = max((unsigned int)10, (unsigned int) ((float)this->desiredTextWidth_ / CHAR_WIDTH));
+        else
+            this->maxCharsPerLine_ = 10;
+
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i]->setWidth(this->desiredTextWidth_);
+            this->consoleOverlayTextAreas_[i]->setTop((int) this->windowH_ * InGameConsole::REL_HEIGHT - 24 - 14*i);
+        }
+
+        this->linesChanged();
+    }
+
+    /**
+        @brief Used to control the actual scrolling and the cursor.
+    */
+    void InGameConsole::tick(float dt)
+    {
+        this->scrollTimer_ += dt;
+        if (this->scrollTimer_ >= 0.01)
+        {
+            float top = this->consoleOverlayContainer_->getTop();
+            this->scrollTimer_ = 0;
+            if (this->scroll_ != 0)
+            {
                 // scroll
-                top = top + 0.02*scroll;
-                consoleOverlayContainer->setTop(top);
+                top = top + 0.02 * this->scroll_;
+                this->consoleOverlayContainer_->setTop(top);
             }
-            if(top <= -1.2*REL_HEIGHT){
+            if (top <= -1.2 * InGameConsole::REL_HEIGHT)
+            {
                 // window has completely scrolled up
-                scroll = 0;
-                consoleOverlay->hide();
-                active = false;
+                this->scroll_ = 0;
+                this->consoleOverlay_->hide();
+                this->active_ = false;
+                Shell::getInstance().unregisterListener(this);
             }
-            if(top >= 0){
+            if (top >= 0)
+            {
                 // window has completely scrolled down
-                scroll = 0;
-                consoleOverlayContainer->setTop(0);
-                active = true;
+                this->scroll_ = 0;
+                this->consoleOverlayContainer_->setTop(0);
+                this->active_ = true;
             }
         }
 
-        cursor += dt;
-        if(cursor >= 2*BLINK) cursor = 0;
-        print(convert2UTF(this->ib_->get()));
-
-// this creates a flickering effect
-        consoleOverlayNoise->setTiling(1, rand()%5+1);
-    }
-
-    /**
-    @brief resizes the console elements. call if window size changes
-    */
-    void InGameConsole::resize(){
-        windowW = GraphicsEngine::getSingleton().getWindowWidth();
-        windowH = GraphicsEngine::getSingleton().getWindowHeight();
-        consoleOverlayBorder->setWidth((int) windowW*REL_WIDTH);
-        consoleOverlayBorder->setHeight((int) windowH*REL_HEIGHT);
-        consoleOverlayNoise->setWidth((int) windowW*REL_WIDTH - 10);
-        consoleOverlayNoise->setHeight((int) windowH*REL_HEIGHT - 5);
-        // now adjust the text lines...
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i]->setWidth(windowW*REL_WIDTH);
-            consoleOverlayTextAreas[i]->setTop((int)windowH*REL_HEIGHT - 24 - 16*i);
-        }
-    }
-
-    /**
-    @brief shows console
-    */
-    void InGameConsole::activate(){
-        consoleOverlay->show();
+        this->cursor_ += dt;
+        if (this->cursor_ >= 2 * InGameConsole::BLINK)
+            this->cursor_ = 0;
+
+        if (this->cursor_ >= InGameConsole::BLINK && this->cursorSymbol_ == '|')
+        {
+            this->cursorSymbol_ = ' ';
+            this->cursorChanged();
+        }
+        else if (this->cursor_ < InGameConsole::BLINK && this->cursorSymbol_ == ' ')
+        {
+            this->cursorSymbol_ = '|';
+            this->cursorChanged();
+        }
+
+        // this creates a flickering effect
+        this->consoleOverlayNoise_->setTiling(1, rand() % 5 + 1);
+    }
+
+    /**
+        @brief Shows the InGameConsole.
+    */
+    void InGameConsole::activate()
+    {
+        InputManager::setInputState(InputManager::IS_CONSOLE);
+        Shell::getInstance().registerListener(this);
+        this->linesChanged();
+
+        this->consoleOverlay_->show();
         // just in case window size has changed...
-        resize();
+        this->resize();
         // scroll down
-        scroll = 1;
+        this->scroll_ = 1;
         // the rest is done by tick
     }
 
     /**
-    @brief hides console
-    */
-    void InGameConsole::deactivate(){
+    @brief Hides the InGameConsole.
+    */
+    void InGameConsole::deactivate()
+    {
         // scroll up
-        scroll = -1;
+        this->scroll_ = -1;
         // the rest is done by tick
-    }
-
-    /**
-    @brief prints string to bottom line
-    @param s string to be printed
-    */
-    void InGameConsole::print(Ogre::UTFString s){
-        if(cursor>BLINK) consoleOverlayTextAreas[0]->setCaption(">" + s);
-        else consoleOverlayTextAreas[0]->setCaption(">" + s + "_");
-    }
-
-    /**
-    @brief shifts all lines up and clears the bottom line
-    */
-    void InGameConsole::newline(){
-        Ogre::UTFString line;
-        for(int i = LINES-1; i>=1; i--){
-            line = consoleOverlayTextAreas[i-1]->getCaption();
-            // don't copy the cursor...
-            int l = line.length();
-            if(!line.empty() && line.substr(l-1) == "_") line.erase(l-1);
-            consoleOverlayTextAreas[i]->setCaption(line);
-        }
-        consoleOverlayTextAreas[0]->setCaption(">");
-    }
-
-    Ogre::UTFString InGameConsole::convert2UTF(std::string s){
+        InputManager::setInputState(InputManager::IS_NORMAL);
+    }
+
+    /**
+        @brief Activates the console.
+    */
+    void InGameConsole::openConsole()
+    {
+        InGameConsole::getInstance().activate();
+    }
+
+    /**
+        @brief Deactivates the console.
+    */
+    void InGameConsole::closeConsole()
+    {
+        InGameConsole::getInstance().deactivate();
+    }
+
+    /**
+        @brief Shifts all output lines one line up
+    */
+    void InGameConsole::shiftLines()
+    {
+        for (unsigned int i = LINES - 1; i > 1; --i)
+        {
+            this->consoleOverlayTextAreas_[i]->setCaption(this->consoleOverlayTextAreas_[i - 1]->getCaption());
+            this->consoleOverlayTextAreas_[i]->setColourTop(this->consoleOverlayTextAreas_[i - 1]->getColourTop());
+            this->consoleOverlayTextAreas_[i]->setColourBottom(this->consoleOverlayTextAreas_[i - 1]->getColourBottom());
+        }
+    }
+
+    void InGameConsole::colourLine(int colourcode, int index)
+    {
+        if (colourcode == -1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.90, 0.90, 0.90, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 1.00, 1.00, 1.00));
+        }
+        else if (colourcode == 1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.25, 0.25, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.50, 0.50, 1.00));
+        }
+        else if (colourcode == 2)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.50, 0.20, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.70, 0.50, 1.00));
+        }
+        else if (colourcode == 3)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.50, 0.50, 0.95, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.80, 1.00, 1.00));
+        }
+        else if (colourcode == 4)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.65, 0.48, 0.44, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.90, 0.90, 1.00));
+        }
+        else if (colourcode == 5)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.40, 0.20, 0.40, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.60, 0.80, 1.00));
+        }
+        else
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.21, 0.69, 0.21, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 1.00, 0.80, 1.00));
+        }
+    }
+
+    /**
+        @brief Prints string to bottom line.
+        @param s String to be printed
+    */
+    void InGameConsole::print(const std::string& text, int index, bool alwaysShift)
+    {
+        char level = 0;
+        if (text.size() > 0)
+            level = text[0];
+
+        std::string output = text;
+
+        if (level >= -1 && level <= 5)
+            output.erase(0, 1);
+
+        if (LINES > index)
+        {
+            this->colourLine(level, index);
+
+            if (index > 0)
+            {
+                unsigned int linesUsed = 1;
+                while (output.size() > this->maxCharsPerLine_)
+                {
+                    ++linesUsed;
+                    this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output.substr(0, this->maxCharsPerLine_)));
+                    output.erase(0, this->maxCharsPerLine_);
+                    output.insert(0, 1, ' ');
+                    if (linesUsed > numLinesShifted_ || alwaysShift)
+                        this->shiftLines();
+                    this->colourLine(level, index);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+                this->numLinesShifted_ = linesUsed;
+            }
+            else
+            {
+                if (output.size() > this->maxCharsPerLine_)
+                {
+                    if (Shell::getInstance().getInputBuffer().getCursorPosition() < this->inputWindowStart_)
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition();
+                    else if (Shell::getInstance().getInputBuffer().getCursorPosition() >= (this->inputWindowStart_ + this->maxCharsPerLine_ - 1))
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition() - this->maxCharsPerLine_ + 1;
+
+                    output = output.substr(this->inputWindowStart_, this->maxCharsPerLine_);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+            }
+        }
+    }
+
+    /**
+        @brief Converts a string into an Ogre::UTFString.
+        @param s The string to convert
+        @return The converted string
+    */
+    Ogre::UTFString InGameConsole::convert2UTF(std::string s)
+    {
         Ogre::UTFString utf;
-        int i;
         Ogre::UTFString::code_point cp;
-        for (i=0; i<(int)s.size(); ++i){
+        for (unsigned int i = 0; i < s.size(); ++i)
+        {
           cp = s[i];
           cp &= 0xFF;
Index: code/branches/network/src/orxonox/console/InGameConsole.h
===================================================================
--- code/branches/network/src/orxonox/console/InGameConsole.h	(revision 1371)
+++ code/branches/network/src/orxonox/console/InGameConsole.h	(revision 1446)
@@ -37,44 +37,63 @@
 
 #include "core/Tickable.h"
-#include "core/InputBuffer.h"
+#include "core/Shell.h"
 
 
 namespace orxonox
 {
-    class _OrxonoxExport InGameConsole : public InputBufferListener
+    class _OrxonoxExport InGameConsole : public Tickable, public ShellListener
     {
         public:
-            InGameConsole(InputBuffer* ib);
-            ~InGameConsole();
-            void listen();
-            void execute();
-            void hintandcomplete();
-            void clear();
-            void removeLast();
-            void exit();
-            void init();
+            static InGameConsole& getInstance();
+
+            void setConfigValues();
             void tick(float dt);
+
             void activate();
             void deactivate();
+            void resize();
+
+            static void openConsole();
+            static void closeConsole();
 
         private:
-            void resize();
-            void print(Ogre::UTFString s);
-            void newline();
-            Ogre::UTFString convert2UTF(std::string s);
+            InGameConsole();
+            InGameConsole(const InGameConsole& other);
+            ~InGameConsole();
 
-            int windowW;
-            int windowH;
-            int scroll;
-            float scrollTimer;
-            float cursor;
-            bool active;
-            InputBuffer* ib_;
-            Ogre::OverlayManager* om;
-            Ogre::Overlay* consoleOverlay;
-            Ogre::OverlayContainer* consoleOverlayContainer;
-            Ogre::PanelOverlayElement* consoleOverlayNoise;
-            Ogre::BorderPanelOverlayElement* consoleOverlayBorder;
-            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas;
+            virtual void linesChanged();
+            virtual void onlyLastLineChanged();
+            virtual void lineAdded();
+            virtual void inputChanged();
+            virtual void cursorChanged();
+            virtual void exit();
+
+            void init();
+            void shiftLines();
+            void colourLine(int colourcode, int index);
+            void print(const std::string& text, int index, bool alwaysShift = false);
+            static Ogre::UTFString convert2UTF(std::string s);
+
+            static float REL_WIDTH;
+            static float REL_HEIGHT;
+            static float BLINK;
+
+            int windowW_;
+            int windowH_;
+            int desiredTextWidth_;
+            unsigned int maxCharsPerLine_;
+            unsigned int numLinesShifted_;
+            int scroll_;
+            float scrollTimer_;
+            float cursor_;
+            unsigned int inputWindowStart_;
+            char cursorSymbol_;
+            bool active_;
+            Ogre::OverlayManager* om_;
+            Ogre::Overlay* consoleOverlay_;
+            Ogre::OverlayContainer* consoleOverlayContainer_;
+            Ogre::PanelOverlayElement* consoleOverlayNoise_;
+            Ogre::BorderPanelOverlayElement* consoleOverlayBorder_;
+            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas_;
     };
 }
