Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 6178


Ignore:
Timestamp:
Nov 29, 2009, 9:25:11 PM (14 years ago)
Author:
rgrieder
Message:

IOConsole: Restructured some code and added more documentation.

Location:
code/branches/presentation2/src/libraries/core
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/presentation2/src/libraries/core/IOConsole.cc

    r6177 r6178  
    4545    IOConsole* IOConsole::singletonPtr_s = NULL;
    4646
     47    //! Extracts the log level associated to a string (first character)
    4748    int IOConsole::extractLogLevel(std::string* text)
    4849    {
     
    265266        }
    266267
    267         // We always assume that the cursor is on the inputline.
     268        // We always assume that the cursor is on the input line.
    268269        // But we cannot always be sure about that, esp. if we scroll the console
    269270        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
     
    469470namespace orxonox
    470471{
     472    //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode
    471473    IOConsole::IOConsole()
    472474        : shell_(new Shell("IOConsole", false, true))
     
    476478        , statusLines_(1)
    477479        , inputLineHeight_(1)
    478         , lastOutputLineHeight_(1)
     480        , lastOutputLineHeight_(0)
    479481    {
    480482        // Disable standard this->cout_ logging
     
    489491        this->terminalWidth_  = screenBufferInfo.dwSize.X;
    490492        this->terminalHeight_ = screenBufferInfo.dwSize.Y;
     493        // Determines where we are in respect to output already written with std::cout
     494        this->inputLineRow_ = screenBufferInfo.dwCursorPosition.Y;
     495/*
    491496        this->lastTerminalWidth_  = this->terminalWidth_;
    492497        this->lastTerminalHeight_ = this->terminalHeight_;
    493         // Determines where we are in respect to output already written with std::cout
    494         this->inputLineRow_ = screenBufferInfo.dwCursorPosition.Y;
     498*/
    495499
    496500        // Cursor already at the end of the screen buffer?
    497501        // (assuming the current input line height is 1)
    498         if (this->inputLineRow_ >= (int)this->terminalHeight_ - (int)this->statusLines_)
    499             this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
     502        if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
     503            SetConsoleCursorPosition(this->stdOutHandle_, makeCOORD(0, this->terminalHeight_ - this->statusLines_));
    500504
    501505        // Prevent input line from overflowing
     
    503507        // Consider that the echo of a command might include the command plus some other characters (assumed max 80)
    504508        // Also put a minimum so the config file parser is not overwhelmed with the command history
    505         this->shell_->getInputBuffer()->setMaxLength(std::min(8192, (maxInputLength - 80) / 2));
     509        this->buffer_->setMaxLength(std::min(8192, (maxInputLength - 80) / 2));
    506510
    507511        // Print input and status line and position cursor
     512        this->inputChanged();
     513        this->cursorChanged();
    508514        this->lastRefreshTime_ = Game::getInstance().getGameClock().getRealMicroseconds();
    509515        this->update(Game::getInstance().getGameClock());
    510         this->inputChanged();
    511         this->cursorChanged();
    512516
    513517        this->shell_->registerListener(this);
    514518    }
    515519
     520    //! Resets std::cout redirection and restores the terminal mode
    516521    IOConsole::~IOConsole()
    517522    {
     
    535540    }
    536541
     542    //! Processes the pending input key strokes, refreshes the status lines and handles std::cout (redirected)
    537543    void IOConsole::update(const Clock& time)
    538544    {
     
    586592
    587593        // TODO: Respect screen buffer size changes
     594/*
    588595        // The user can manually adjust the screen buffer size on Windows
    589596        // And we don't want to screw the console because of that
    590         //this->lastTerminalWidth_ = this->terminalWidth_;
    591         //this->lastTerminalHeight_ = this->terminalHeight_;
    592         //this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position
     597        this->lastTerminalWidth_ = this->terminalWidth_;
     598        this->lastTerminalHeight_ = this->terminalHeight_;
     599        this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position
    593600        // Is there still enough space below the cursor for the status line(s)?
    594         //if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
    595         //    this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
     601        if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
     602            this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
     603*/
    596604
    597605        // Refresh status line 5 times per second
     
    610618    }
    611619
     620    //! Prints output text. Similar to writeText, but sets the colour according to the output level
    612621    void IOConsole::printOutputLine(const std::string& text, const COORD& pos)
    613622    {
     
    619628        switch (level)
    620629        {
    621         case  1: colour = FOREGROUND_RED | FOREGROUND_INTENSITY; break;
    622         case  2: colour = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break;
    623         case  3: colour = FOREGROUND_INTENSITY; break;
    624         case  4: colour = FOREGROUND_INTENSITY; break;
    625         default: colour = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN; break;
     630        case  1: colour = FOREGROUND_INTENSITY                    | FOREGROUND_RED ; break;
     631        case  2: colour = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED ; break;
     632        case  3: colour = FOREGROUND_INTENSITY                                     ; break;
     633        case  4: colour = FOREGROUND_INTENSITY                                     ; break;
     634        default: colour =                        FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ; break;
    626635        }
    627636
     
    630639    }
    631640
     641    //! Prints all status lines with current content
    632642    void IOConsole::printStatusLines()
    633643    {
     
    638648        // Clear rest of the line by inserting spaces
    639649        oss << std::string(this->terminalWidth_ - oss.str().size(), ' ');
    640         COORD pos = {0, this->inputLineRow_ + this->inputLineHeight_};
    641         this->writeText(oss.str(), pos, FOREGROUND_GREEN);
    642     }
    643 
     650        this->writeText(oss.str(), makeCOORD(0, this->inputLineRow_ + this->inputLineHeight_), FOREGROUND_GREEN);
     651    }
     652
     653    //! Changes the console parameters for unbuffered input
    644654    void IOConsole::setTerminalMode()
    645655    {
     
    657667    }
    658668
     669    //! Restores the console parameters
    659670    void IOConsole::resetTerminalMode()
    660671    {
     
    662673    }
    663674
    664     //! Moves the console cursor around and clamps its position to fit into the screen buffer
    665     void IOConsole::moveCursor(int dx, int dy)
    666     {
    667         CONSOLE_SCREEN_BUFFER_INFO info;
    668         GetConsoleScreenBufferInfo(this->stdOutHandle_, &info);
    669         SHORT& x = info.dwCursorPosition.X;
    670         x = clamp(x + dx, 0, info.dwSize.X - 1);
    671         SHORT& y = info.dwCursorPosition.Y;
    672         y = clamp(y + dy, 0, info.dwSize.Y - 1);
    673         SetConsoleCursorPosition(this->stdOutHandle_, info.dwCursorPosition);
    674     }
    675 
     675    //! Sets this->terminalWidth_ and this->terminalHeight_
    676676    void IOConsole::getTerminalSize()
    677677    {
     
    682682    }
    683683
     684    //! Writes arbitrary text to the console with a certain colour and screen buffer position
    684685    void IOConsole::writeText(const std::string& text, const COORD& coord, WORD attributes)
    685686    {
    686687        DWORD count;
    687688        WriteConsoleOutputCharacter(stdOutHandle_, text.c_str(), text.size(), coord, &count);
    688         WORD* attributeBuf = new WORD[text.size()];
    689         for (unsigned int i = 0; i < text.size(); ++i)
    690             attributeBuf[i] = attributes;
    691         WriteConsoleOutputAttribute(stdOutHandle_, attributeBuf, text.size(), coord, &count);
    692     }
    693 
    694     void IOConsole::createNewOutputLines(unsigned int lines)
     689        FillConsoleOutputAttribute(stdOutHandle_, attributes, text.size(), coord, &count);
     690    }
     691
     692    /** Scrolls the console screen buffer to create empty lines above the input line.
     693    @details
     694        If the input and status lines are already at the bottom of the screen buffer
     695        the whole output gets scrolled up. In the other case the input and status
     696        lines get scrolled down.
     697        In any case the status and input lines get scrolled down as far as possible.
     698    @param lines
     699        Number of lines to be inserted. Behavior for negative values is undefined.
     700    */
     701    void IOConsole::createNewOutputLines(int lines)
    695702    {
    696703        CHAR_INFO fillChar = {' ', FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
    697         // Check whether we're already at the bottom
    698         if (this->inputLineRow_ + lines > this->terminalHeight_ - this->statusLines_ - this->inputLineHeight_)
    699         {
    700             // Scroll output up
    701             SMALL_RECT oldRect = {0, lines, this->terminalWidth_ - 1, this->inputLineRow_ - 1};
    702             COORD newPos = {0, 0};
    703             ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, newPos, &fillChar);
    704         }
    705         else
     704        // Lines to scroll input/status down (if possible)
     705        int linesDown = clamp(terminalHeight_ - inputLineRow_ - inputLineHeight_ - statusLines_, 0, lines);
     706        if (linesDown > 0)
    706707        {
    707708            // Scroll input and status lines down
    708             SMALL_RECT oldRect = {0, this->inputLineRow_, this->terminalWidth_ - 1, this->inputLineRow_ + this->statusLines_ + this->inputLineHeight_ - 1};
    709             this->inputLineRow_ += lines;
    710             COORD newPos = {0, this->inputLineRow_};
    711             ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, newPos, &fillChar);
     709            SMALL_RECT oldRect = {0, this->inputLineRow_,
     710                this->terminalWidth_ - 1, this->inputLineRow_ + this->inputLineHeight_ + this->statusLines_ - 1};
     711            this->inputLineRow_ += linesDown;
     712            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, this->inputLineRow_), &fillChar);
    712713            // Move cursor down to the new bottom so the user can see the status lines
    713714            COORD pos = {0, this->inputLineRow_ + this->inputLineHeight_ - 1 + this->statusLines_};
     
    716717            this->cursorChanged();
    717718        }
     719        // Check how many lines we still have to scroll up the output
     720        if (lines - linesDown > 0)
     721        {
     722            // Scroll output up
     723            SMALL_RECT oldRect = {0, lines - linesDown, this->terminalWidth_ - 1, this->inputLineRow_ - 1};
     724            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, 0), &fillChar);
     725        }
    718726    }
    719727
     
    722730    // ###############################
    723731
    724     //! Called if the text in the input-line has changed
     732    //! Called if the text in the input line has changed
    725733    void IOConsole::inputChanged()
    726734    {
    727         int inputLineLength = this->promptString_.size() + this->shell_->getInput().size();
    728         int lineHeight = 1 + inputLineLength / this->terminalWidth_;
    729         int newLines = lineHeight - this->inputLineHeight_;
     735        int newInputLineLength = this->promptString_.size() + this->shell_->getInput().size();
     736        int newInputLineHeight = 1 + newInputLineLength / this->terminalWidth_;
     737        int newLines = newInputLineHeight - this->inputLineHeight_;
    730738        if (newLines > 0)
    731739        {
    732740            // Abuse this function to scroll the console
    733741            this->createNewOutputLines(newLines);
    734             this->inputLineRow_ -= newLines; // Undo
     742            // Either Compensate for side effects (input/status lines scrolled down)
     743            // or we have to do this anyway (output scrolled up)
     744            this->inputLineRow_ -= newLines;
    735745        }
    736746        else if (newLines < 0)
    737747        {
    738748            // Scroll status lines up
    739             SMALL_RECT oldRect = {0, this->inputLineRow_ + this->inputLineHeight_, this->terminalWidth_ - 1, this->inputLineRow_ + this->inputLineHeight_ + this->statusLines_};
    740             COORD newPos = {0, this->inputLineRow_ + this->inputLineHeight_ + newLines};
     749            int statusLineRow = this->inputLineRow_ + this->inputLineHeight_;
     750            SMALL_RECT oldRect = {0, statusLineRow, this->terminalWidth_ - 1, statusLineRow + this->statusLines_};
    741751            CHAR_INFO fillChar = {' ', FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
    742             ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, newPos, &fillChar);
     752            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, NULL, makeCOORD(0, statusLineRow + newLines), &fillChar);
    743753            // Clear potential leftovers
    744754            if (-newLines - this->statusLines_ > 0)
    745755            {
    746                 COORD pos = {0, this->inputLineRow_ + lineHeight + this->statusLines_};
     756                COORD pos = {0, this->inputLineRow_ + newInputLineHeight + this->statusLines_};
    747757                this->writeText(std::string((-newLines - this->statusLines_) * this->terminalWidth_, ' '), pos);
    748758            }
    749759        }
    750         this->inputLineHeight_ = lineHeight;
    751 
    752         // Print the whole line, including spaces to erase leftovers
    753         COORD pos = {0, this->inputLineRow_};
    754         WORD colour = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
    755         this->writeText(this->promptString_ + this->shell_->getInput() + std::string(this->terminalWidth_ - inputLineLength % this->terminalWidth_, ' '), pos, colour);
     760        this->inputLineHeight_ = newInputLineHeight;
     761
     762        // Print the whole line, including spaces that erase leftovers
     763        std::string inputLine = this->promptString_ + this->shell_->getInput();
     764        inputLine += std::string(this->terminalWidth_ - newInputLineLength % this->terminalWidth_, ' ');
     765        this->writeText(inputLine, makeCOORD(0, this->inputLineRow_), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
    756766        // If necessary, move cursor
    757767        if (newLines != 0)
     
    762772    void IOConsole::cursorChanged()
    763773    {
     774        int rawCursorPos = this->promptString_.size() + this->buffer_->getCursorPosition();
     775        // Compensate for cursor further to the right than the terminal width
    764776        COORD pos;
    765         unsigned int total = this->promptString_.size() + this->buffer_->getCursorPosition();
    766         // Compensate for cursor further to the right than the terminal width
    767         pos.X = total % this->terminalWidth_;
    768         pos.Y = this->inputLineRow_ + total / this->terminalWidth_;
     777        pos.X = rawCursorPos % this->terminalWidth_;
     778        pos.Y = this->inputLineRow_ + rawCursorPos / this->terminalWidth_;
    769779        SetConsoleCursorPosition(stdOutHandle_, pos);
    770780    }
     
    773783    void IOConsole::onlyLastLineChanged()
    774784    {
    775         int lineHeight = 1 + this->shell_->getNewestLineIterator()->size() / this->terminalWidth_;
    776         int newLines = lineHeight - this->lastOutputLineHeight_;
    777         this->lastOutputLineHeight_ = lineHeight;
    778         if (newLines > 0)
     785        int newLineHeight = 1 + this->shell_->getNewestLineIterator()->size() / this->terminalWidth_;
     786        // Compute the number of new lines needed
     787        int newLines = newLineHeight - this->lastOutputLineHeight_;
     788        this->lastOutputLineHeight_ = newLineHeight;
     789        // Scroll console if necessary
     790        if (newLines > 0) // newLines < 0 is assumed impossible
    779791            this->createNewOutputLines(newLines);
    780         // Write text (assuming it is longer than the previous text)
    781         assert(newLines >= 0);
    782         COORD pos = {0, this->inputLineRow_ - lineHeight};
    783         this->printOutputLine(*(this->shell_->getNewestLineIterator()), pos);
    784     }
    785 
    786     //! Called if a new output-line was added
     792        this->printOutputLine(*(this->shell_->getNewestLineIterator()), makeCOORD(0, this->inputLineRow_ - newLineHeight));
     793    }
     794
     795    //! Called if a new output line was added
    787796    void IOConsole::lineAdded()
    788797    {
     798        // Scroll console
    789799        this->lastOutputLineHeight_ = 1 + this->shell_->getNewestLineIterator()->size() / this->terminalWidth_;
    790         if (this->lastOutputLineHeight_ > 0)
    791             this->createNewOutputLines(this->lastOutputLineHeight_);
     800        this->createNewOutputLines(this->lastOutputLineHeight_);
    792801        // Write the text
    793802        COORD pos = {0, this->inputLineRow_ - this->lastOutputLineHeight_};
  • code/branches/presentation2/src/libraries/core/IOConsole.h

    r6177 r6178  
    6262        void setTerminalMode();
    6363        void getTerminalSize();
    64         int extractLogLevel(std::string* text);
    65 
    6664        void printStatusLines();
     65        static int extractLogLevel(std::string* text);
    6766
    6867        // Methods from ShellListener
     
    7473        void executed();
    7574        void exit();
     75
    7676        Shell*                  shell_;
    7777        InputBuffer*            buffer_;
    7878        std::ostream            cout_;
    7979        std::ostringstream      origCout_;
    80         unsigned int            terminalWidth_;
    81         unsigned int            terminalHeight_;
    82         unsigned int            lastTerminalWidth_;
    83         unsigned int            lastTerminalHeight_;
     80        int                     terminalWidth_;
     81        int                     terminalHeight_;
     82        int                     lastTerminalWidth_;
     83        int                     lastTerminalHeight_;
    8484        const std::string       promptString_;
    8585
    8686#ifdef ORXONOX_PLATFORM_UNIX
    8787        bool willPrintStatusLines();
     88        void printInputLine();
    8889        void printOutputLine(const std::string& line);
    89         void printInputLine();
    9090        static void resetTerminalMode();
    9191
    9292        bool                    bPrintStatusLine_;
    9393        bool                    bStatusPrinted_;
    94         std::vector<unsigned>   statusLineWidths_;
    95         unsigned int            statusLineMaxWidth_;
    96         static const unsigned   minOutputLines_ = 3;
     94        std::vector<int>        statusLineWidths_;
     95        int                     statusLineMaxWidth_;
     96        static const            minOutputLines_ = 3;
    9797        termios*                originalTerminalSettings_;
    9898
     
    101101        void moveCursor(int dx, int dy);
    102102        void writeText(const std::string& text, const COORD& pos, WORD attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
    103         void createNewOutputLines(unsigned int lines);
     103        void createNewOutputLines(int lines);
    104104        void printOutputLine(const std::string& line, const COORD& pos);
     105
     106        static inline COORD makeCOORD(int x, int y)
     107        {
     108            COORD val = {x, y};
     109            return val;
     110        }
    105111
    106112        DWORD                   originalTerminalSettings_;
     
    108114        HANDLE                  stdOutHandle_;
    109115        int                     inputLineRow_;
    110         unsigned int            inputLineHeight_;
    111         const unsigned int      statusLines_;
    112         unsigned int            lastOutputLineHeight_;
     116        int                     inputLineHeight_;
     117        const int               statusLines_;
     118        int                     lastOutputLineHeight_;
    113119        uint64_t                lastRefreshTime_;
    114120#endif
Note: See TracChangeset for help on using the changeset viewer.