Index: code/trunk/src/libraries/core/command/IOConsoleWindows.cc
===================================================================
--- code/trunk/src/libraries/core/IOConsole.cc	(revision 6746)
+++ code/trunk/src/libraries/core/command/IOConsoleWindows.cc	(revision 7287)
@@ -21,5 +21,4 @@
  *
  *   Author:
- *      Oliver Scheuss
  *      Reto Grieder
  *   Co-authors:
@@ -35,424 +34,11 @@
 #include "util/Clock.h"
 #include "util/Math.h"
-#include "Game.h"
-#include "input/InputBuffer.h"
-
-// ##########################
-// ###   Mutual methods   ###
-// ##########################
+#include "core/Game.h"
+#include "core/input/InputBuffer.h"
+
 namespace orxonox
 {
     IOConsole* IOConsole::singletonPtr_s = NULL;
 
-    // ###############################
-    // ###  ShellListener methods  ###
-    // ###############################
-
-    //! Called if all output-lines have to be reprinted
-    void IOConsole::linesChanged()
-    {
-        // Method only gets called upon start to draw all the lines
-        // or when scrolling. But scrolling is disabled and the output
-        // is already in std::cout when we start the IOConsole
-    }
-
-    //! Called if a command is about to be executed
-    void IOConsole::executed()
-    {
-        this->shell_->addOutput(this->promptString_ + this->shell_->getInput() + '\n', Shell::Command);
-    }
-
-    //! Called if the console gets closed
-    void IOConsole::exit()
-    {
-        // Exit is not an option, just do nothing (Shell doesn't really exit too)
-    }
-}
-
-#ifdef ORXONOX_PLATFORM_UNIX
-// ###############################
-// ###   Unix Implementation   ###
-// ###############################
-
-#include <termios.h>
-#include <sys/ioctl.h>
-
-namespace orxonox
-{
-    namespace EscapeMode
-    {
-        enum Value
-        {
-            None,
-            First,
-            Second
-        };
-    }
-
-    IOConsole::IOConsole()
-        : shell_(new Shell("IOConsole", false))
-        , buffer_(shell_->getInputBuffer())
-        , cout_(std::cout.rdbuf())
-        , promptString_("orxonox # ")
-        , bStatusPrinted_(false)
-        , originalTerminalSettings_(0)
-    {
-        this->setTerminalMode();
-        this->shell_->registerListener(this);
-
-        // Manually set the widths of the individual status lines
-        this->statusLineWidths_.push_back(29);
-        this->statusLineMaxWidth_ = 29;
-
-        this->getTerminalSize();
-        this->lastTerminalWidth_ = this->terminalWidth_;
-        this->lastTerminalHeight_ = this->terminalHeight_;
-
-        // Disable standard std::cout logging
-        OutputHandler::getInstance().disableCout();
-        // Redirect std::cout to an ostringstream
-        // (Other part is in the initialiser list)
-        std::cout.rdbuf(this->origCout_.rdbuf());
-
-        // Make sure we make way for the status lines
-        this->preUpdate(Game::getInstance().getGameClock());
-    }
-
-    IOConsole::~IOConsole()
-    {
-        // Process output written to std::cout in the meantime
-        std::cout.flush();
-        if (!this->origCout_.str().empty())
-            this->shell_->addOutput(this->origCout_.str(), Shell::None);
-        // Erase input and status lines
-        this->cout_ << "\033[1G\033[J";
-        // Move cursor to the bottom
-        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
-        // Scroll terminal to compensate for erased lines
-        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'T';
-
-        resetTerminalMode();
-        this->shell_->destroy();
-
-        // Restore this->cout_ redirection
-        std::cout.rdbuf(this->cout_.rdbuf());
-        // Enable standard std::cout logging again
-        OutputHandler::getInstance().enableCout();
-    }
-
-    void IOConsole::preUpdate(const Clock& time)
-    {
-        unsigned char c;
-        std::string escapeSequence;
-        EscapeMode::Value escapeMode = EscapeMode::None;
-        while (std::cin.good())
-        {
-            c = std::cin.get();
-            if (!std::cin.good())
-                break;
-
-            if (escapeMode == EscapeMode::First && (c == '[' || c=='O') )
-                escapeMode = EscapeMode::Second;
-            // Get Alt+Tab combination when switching applications
-            else if (escapeMode == EscapeMode::First && c == '\t')
-            {
-                this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, '\t', KeyboardModifier::Alt));
-                escapeMode = EscapeMode::None;
-            }
-            else if (escapeMode == EscapeMode::Second)
-            {
-                escapeSequence += c;
-                escapeMode = EscapeMode::None;
-                if      (escapeSequence == "A")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Up,       0, 0));
-                else if (escapeSequence == "B")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Down,     0, 0));
-                else if (escapeSequence == "C")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Right,    0, 0));
-                else if (escapeSequence == "D")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Left,     0, 0));
-                else if (escapeSequence == "1~" || escapeSequence == "H")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Home,     0, 0));
-                else if (escapeSequence == "2~")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert,   0, 0));
-                else if (escapeSequence == "3~")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete,   0, 0));
-                else if (escapeSequence == "4~" || escapeSequence == "F")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::End,      0, 0));
-                else if (escapeSequence == "5~")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp,   0, 0));
-                else if (escapeSequence == "6~")
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, 0, 0));
-                else
-                    // Waiting for sequence to complete
-                    // If the user presses ESC and then '[' or 'O' while the loop is not
-                    // running (for instance while loading), the whole sequence gets dropped
-                    escapeMode = EscapeMode::Second;
-            }
-            else // not in an escape sequence OR user might have pressed just ESC
-            {
-                if (escapeMode == EscapeMode::First)
-                {
-                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, c, 0));
-                    escapeMode = EscapeMode::None;
-                }
-                if (c == '\033')
-                {
-                    escapeMode = EscapeMode::First;
-                    escapeSequence.clear();
-                }
-                else
-                {
-                    KeyCode::ByEnum code;
-                    switch (c)
-                    {
-                    case '\n'  : case '\r': code = KeyCode::Return; break;
-                    case '\177': case '\b': code = KeyCode::Back;   break;
-                    case '\t'             : code = KeyCode::Tab;    break;
-                    default:
-                        // We don't encode the key code (would be a very large switch)
-                        // because the InputBuffer will only insert the text anyway
-                        // Replacement character is simply KeyCode::A
-                        code = KeyCode::A;
-                    }
-                    this->buffer_->buttonPressed(KeyEvent(code, c, 0));
-                }
-            }
-        }
-        // Reset error flags in std::cin
-        std::cin.clear();
-
-        // If there is still an escape key pending (escape key ONLY), then
-        // it sure isn't an escape sequence anymore
-        if (escapeMode == EscapeMode::First)
-            this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, '\033', 0));
-
-        // Determine terminal width and height
-        this->lastTerminalWidth_ = this->terminalWidth_;
-        this->lastTerminalHeight_ = this->terminalHeight_;
-        this->getTerminalSize();
-
-        int heightDiff = this->terminalHeight_ - this->lastTerminalHeight_;
-        if (this->bStatusPrinted_ && heightDiff < 0)
-        {
-            // Terminal width has shrunk. The cursor will still be on the input line,
-            // but that line might very well be the last
-            int newLines = std::min((int)this->statusLineWidths_.size(), -heightDiff);
-            // Scroll terminal to create new lines
-            this->cout_ << "\033[" << newLines << 'S';
-        }
-
-        if (!this->bStatusPrinted_ && this->willPrintStatusLines())
-        {
-            // Scroll console to make way for status lines
-            this->cout_ << "\033[" << this->statusLineWidths_.size() << 'S';
-            this->bStatusPrinted_ = true;
-        }
-
-        // We always assume that the cursor is on the input line.
-        // But we cannot always be sure about that, esp. if we scroll the console
-        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
-        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'A';
-
-        // Erase status and input lines
-        this->cout_ << "\033[1G\033[J";
-        this->printInputLine();
-        this->printStatusLines();
-        this->cout_.flush();
-
-        // Process output written to std::cout
-        std::cout.flush();
-        if (!this->origCout_.str().empty())
-        {
-            this->shell_->addOutput(this->origCout_.str(), Shell::None);
-            this->origCout_.str("");
-        }
-    }
-
-    void IOConsole::printOutputLine(const std::string& text, Shell::LineType type)
-    {
-/*
-        // Colour line
-        switch (type)
-        {
-        case Shell::None:    this->cout_ << "\033[37m"; break;
-        case Shell::Error:   this->cout_ << "\033[91m"; break;
-        case Shell::Warning: this->cout_ << "\033[31m"; break;
-        case Shell::Info:    this->cout_ << "\033[34m"; break;
-        case Shell::Debug:   this->cout_ << "\033[36m"; break;
-        case Shell::Verbose: this->cout_ << "\033[35m"; break;
-        case Shell::Ultra:   this->cout_ << "\033[37m"; break;
-        default: break;
-        }
-*/
-
-        // Print output line
-        this->cout_ << text;
-
-        // Reset colour to white
-//        this->cout_ << "\033[37m";
-    }
-
-    void IOConsole::printInputLine()
-    {
-        // Set cursor to the beginning of the line and erase the line
-        this->cout_ << "\033[1G\033[K";
-        // Indicate a command prompt
-        this->cout_ << this->promptString_;
-        // Save cursor position
-        this->cout_ << "\033[s";
-        // Print command line buffer
-        this->cout_ << this->shell_->getInput();
-        // Restore cursor position and move it to the right
-        this->cout_ << "\033[u";
-        if (this->buffer_->getCursorPosition() > 0)
-            this->cout_ << "\033[" << this->buffer_->getCursorPosition() << 'C';
-    }
-
-    void IOConsole::printStatusLines()
-    {
-        if (this->willPrintStatusLines())
-        {
-            // Save cursor position
-            this->cout_ << "\033[s";
-            // Move cursor down (don't create a new line here because the buffer might flush then!)
-            this->cout_ << "\033[1B\033[1G";
-            this->cout_ << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
-            this->cout_ <<               std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
-            // Restore cursor position
-            this->cout_ << "\033[u";
-            this->bStatusPrinted_ = true;
-        }
-        else
-            this->bStatusPrinted_ = false;
-    }
-
-    void IOConsole::setTerminalMode()
-    {
-        termios new_settings;
-        this->originalTerminalSettings_ = new termios();
-
-        tcgetattr(0, this->originalTerminalSettings_);
-        new_settings = *this->originalTerminalSettings_;
-        new_settings.c_lflag &= ~(ICANON | ECHO);
-        //new_settings.c_lflag |= (ISIG | IEXTEN);
-        new_settings.c_cc[VTIME] = 0;
-        new_settings.c_cc[VMIN]  = 0;
-        tcsetattr(0, TCSANOW, &new_settings);
-        atexit(&IOConsole::resetTerminalMode);
-    }
-
-    /*static*/ void IOConsole::resetTerminalMode()
-    {
-        if (IOConsole::singletonPtr_s && IOConsole::singletonPtr_s->originalTerminalSettings_)
-        {
-            tcsetattr(0, TCSANOW, IOConsole::singletonPtr_s->originalTerminalSettings_);
-            delete IOConsole::singletonPtr_s->originalTerminalSettings_;
-            IOConsole::singletonPtr_s->originalTerminalSettings_ = 0;
-        }
-    }
-
-    void IOConsole::getTerminalSize()
-    {
-#ifdef TIOCGSIZE
-        struct ttysize win;
-        if (!ioctl(STDIN_FILENO, TIOCGSIZE, &win))
-        {
-            this->terminalWidth_  = win.ts_cols;
-            this->terminalHeight_ = win.ts_lines;
-            return;
-        }
-#elif defined TIOCGWINSZ
-        struct winsize win;
-        if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
-        {
-            this->terminalWidth_  = win.ws_col;
-            this->terminalHeight_ = win.ws_row;
-            return;
-        }
-#else
-        const char* s = getenv("COLUMNS");
-        this->terminalWidth_  = s ? strtol(s, NULL, 10) : 80;
-        s = getenv("LINES");
-        this->terminalHeight_ = s ? strtol(s, NULL, 10) : 24;
-        return;
-#endif
-        this->terminalWidth_  = 80;
-        this->terminalHeight_ = 24;
-    }
-
-    inline bool IOConsole::willPrintStatusLines()
-    {
-        return !this->statusLineWidths_.empty()
-             && this->terminalWidth_  >= this->statusLineMaxWidth_
-             && this->terminalHeight_ >= this->minOutputLines_ + (int)this->statusLineWidths_.size();
-    }
-
-    // ###############################
-    // ###  ShellListener methods  ###
-    // ###############################
-
-    //! Called if only the last output-line has changed
-    void IOConsole::onlyLastLineChanged()
-    {
-        // Save cursor position and move it to the beginning of the first output line
-        this->cout_ << "\033[s\033[1A\033[1G";
-        // Erase the line
-        this->cout_ << "\033[K";
-        // Reprint the last output line
-        this->printOutputLine(this->shell_->getNewestLineIterator()->first, this->shell_->getNewestLineIterator()->second);
-        // Restore cursor
-        this->cout_ << "\033[u";
-        this->cout_.flush();
-    }
-
-    //! Called if a new output-line was added
-    void IOConsole::lineAdded()
-    {
-        int newLines = this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_ + 1;
-        // Create new lines by scrolling the screen
-        this->cout_ << "\033[" << newLines << 'S';
-        // Move cursor to the beginning of the new (last) output line
-        this->cout_ << "\033[" << newLines << "A\033[1G";
-        // Erase screen from here
-        this->cout_ << "\033[J";
-        // Print the new output lines
-        for (int i = 0; i < newLines; ++i)
-        {
-            Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
-            this->printOutputLine(it->first.substr(i*this->terminalWidth_, this->terminalWidth_), it->second);
-        }
-        // Move cursor down
-        this->cout_ << "\033[1B\033[1G";
-        // Print status and input lines
-        this->printInputLine();
-        this->printStatusLines();
-        this->cout_.flush();
-    }
-
-    //! Called if the text in the input-line has changed
-    void IOConsole::inputChanged()
-    {
-        this->printInputLine();
-        this->cout_.flush();
-    }
-
-    //! Called if the position of the cursor in the input-line has changed
-    void IOConsole::cursorChanged()
-    {
-        this->printInputLine();
-        this->cout_.flush();
-    }
-}
-
-#elif defined(ORXONOX_PLATFORM_WINDOWS)
-// ##################################
-// ###   Windows Implementation   ###
-// ##################################
-
-#include <windows.h>
-
-namespace orxonox
-{
     //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode
     IOConsole::IOConsole()
@@ -720,4 +306,24 @@
     // ###############################
 
+    //! Called if all output-lines have to be reprinted
+    void IOConsole::linesChanged()
+    {
+        // Method only gets called upon start to draw all the lines
+        // or when scrolling. But scrolling is disabled and the output
+        // is already in std::cout when we start the IOConsole
+    }
+
+    //! Called if a command is about to be executed
+    void IOConsole::executed()
+    {
+        this->shell_->addOutput(this->promptString_ + this->shell_->getInput() + '\n', Shell::Command);
+    }
+
+    //! Called if the console gets closed
+    void IOConsole::exit()
+    {
+        // Exit is not an option, just do nothing (Shell doesn't really exit too)
+    }
+
     //! Called if the text in the input line has changed
     void IOConsole::inputChanged()
@@ -796,4 +402,2 @@
     }
 }
-
-#endif /* ORXONOX_PLATFORM_UNIX */
