- Timestamp:
- Nov 29, 2009, 9:25:11 PM (15 years ago)
- Location:
- code/branches/presentation2/src/libraries/core
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/presentation2/src/libraries/core/IOConsole.cc
r6177 r6178 45 45 IOConsole* IOConsole::singletonPtr_s = NULL; 46 46 47 //! Extracts the log level associated to a string (first character) 47 48 int IOConsole::extractLogLevel(std::string* text) 48 49 { … … 265 266 } 266 267 267 // We always assume that the cursor is on the input line.268 // We always assume that the cursor is on the input line. 268 269 // But we cannot always be sure about that, esp. if we scroll the console 269 270 this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B'; … … 469 470 namespace orxonox 470 471 { 472 //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode 471 473 IOConsole::IOConsole() 472 474 : shell_(new Shell("IOConsole", false, true)) … … 476 478 , statusLines_(1) 477 479 , inputLineHeight_(1) 478 , lastOutputLineHeight_( 1)480 , lastOutputLineHeight_(0) 479 481 { 480 482 // Disable standard this->cout_ logging … … 489 491 this->terminalWidth_ = screenBufferInfo.dwSize.X; 490 492 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 /* 491 496 this->lastTerminalWidth_ = this->terminalWidth_; 492 497 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 */ 495 499 496 500 // Cursor already at the end of the screen buffer? 497 501 // (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_)); 500 504 501 505 // Prevent input line from overflowing … … 503 507 // Consider that the echo of a command might include the command plus some other characters (assumed max 80) 504 508 // 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)); 506 510 507 511 // Print input and status line and position cursor 512 this->inputChanged(); 513 this->cursorChanged(); 508 514 this->lastRefreshTime_ = Game::getInstance().getGameClock().getRealMicroseconds(); 509 515 this->update(Game::getInstance().getGameClock()); 510 this->inputChanged();511 this->cursorChanged();512 516 513 517 this->shell_->registerListener(this); 514 518 } 515 519 520 //! Resets std::cout redirection and restores the terminal mode 516 521 IOConsole::~IOConsole() 517 522 { … … 535 540 } 536 541 542 //! Processes the pending input key strokes, refreshes the status lines and handles std::cout (redirected) 537 543 void IOConsole::update(const Clock& time) 538 544 { … … 586 592 587 593 // TODO: Respect screen buffer size changes 594 /* 588 595 // The user can manually adjust the screen buffer size on Windows 589 596 // 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 position597 this->lastTerminalWidth_ = this->terminalWidth_; 598 this->lastTerminalHeight_ = this->terminalHeight_; 599 this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position 593 600 // 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 */ 596 604 597 605 // Refresh status line 5 times per second … … 610 618 } 611 619 620 //! Prints output text. Similar to writeText, but sets the colour according to the output level 612 621 void IOConsole::printOutputLine(const std::string& text, const COORD& pos) 613 622 { … … 619 628 switch (level) 620 629 { 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; 626 635 } 627 636 … … 630 639 } 631 640 641 //! Prints all status lines with current content 632 642 void IOConsole::printStatusLines() 633 643 { … … 638 648 // Clear rest of the line by inserting spaces 639 649 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 644 654 void IOConsole::setTerminalMode() 645 655 { … … 657 667 } 658 668 669 //! Restores the console parameters 659 670 void IOConsole::resetTerminalMode() 660 671 { … … 662 673 } 663 674 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_ 676 676 void IOConsole::getTerminalSize() 677 677 { … … 682 682 } 683 683 684 //! Writes arbitrary text to the console with a certain colour and screen buffer position 684 685 void IOConsole::writeText(const std::string& text, const COORD& coord, WORD attributes) 685 686 { 686 687 DWORD count; 687 688 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) 695 702 { 696 703 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) 706 707 { 707 708 // 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); 712 713 // Move cursor down to the new bottom so the user can see the status lines 713 714 COORD pos = {0, this->inputLineRow_ + this->inputLineHeight_ - 1 + this->statusLines_}; … … 716 717 this->cursorChanged(); 717 718 } 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 } 718 726 } 719 727 … … 722 730 // ############################### 723 731 724 //! Called if the text in the input -line has changed732 //! Called if the text in the input line has changed 725 733 void IOConsole::inputChanged() 726 734 { 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_; 730 738 if (newLines > 0) 731 739 { 732 740 // Abuse this function to scroll the console 733 741 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; 735 745 } 736 746 else if (newLines < 0) 737 747 { 738 748 // 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_}; 741 751 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); 743 753 // Clear potential leftovers 744 754 if (-newLines - this->statusLines_ > 0) 745 755 { 746 COORD pos = {0, this->inputLineRow_ + lineHeight + this->statusLines_};756 COORD pos = {0, this->inputLineRow_ + newInputLineHeight + this->statusLines_}; 747 757 this->writeText(std::string((-newLines - this->statusLines_) * this->terminalWidth_, ' '), pos); 748 758 } 749 759 } 750 this->inputLineHeight_ = lineHeight;751 752 // Print the whole line, including spaces t oerase leftovers753 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); 756 766 // If necessary, move cursor 757 767 if (newLines != 0) … … 762 772 void IOConsole::cursorChanged() 763 773 { 774 int rawCursorPos = this->promptString_.size() + this->buffer_->getCursorPosition(); 775 // Compensate for cursor further to the right than the terminal width 764 776 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_; 769 779 SetConsoleCursorPosition(stdOutHandle_, pos); 770 780 } … … 773 783 void IOConsole::onlyLastLineChanged() 774 784 { 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 779 791 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 787 796 void IOConsole::lineAdded() 788 797 { 798 // Scroll console 789 799 this->lastOutputLineHeight_ = 1 + this->shell_->getNewestLineIterator()->size() / this->terminalWidth_; 790 if (this->lastOutputLineHeight_ > 0) 791 this->createNewOutputLines(this->lastOutputLineHeight_); 800 this->createNewOutputLines(this->lastOutputLineHeight_); 792 801 // Write the text 793 802 COORD pos = {0, this->inputLineRow_ - this->lastOutputLineHeight_}; -
code/branches/presentation2/src/libraries/core/IOConsole.h
r6177 r6178 62 62 void setTerminalMode(); 63 63 void getTerminalSize(); 64 int extractLogLevel(std::string* text);65 66 64 void printStatusLines(); 65 static int extractLogLevel(std::string* text); 67 66 68 67 // Methods from ShellListener … … 74 73 void executed(); 75 74 void exit(); 75 76 76 Shell* shell_; 77 77 InputBuffer* buffer_; 78 78 std::ostream cout_; 79 79 std::ostringstream origCout_; 80 unsigned intterminalWidth_;81 unsigned intterminalHeight_;82 unsigned intlastTerminalWidth_;83 unsigned intlastTerminalHeight_;80 int terminalWidth_; 81 int terminalHeight_; 82 int lastTerminalWidth_; 83 int lastTerminalHeight_; 84 84 const std::string promptString_; 85 85 86 86 #ifdef ORXONOX_PLATFORM_UNIX 87 87 bool willPrintStatusLines(); 88 void printInputLine(); 88 89 void printOutputLine(const std::string& line); 89 void printInputLine();90 90 static void resetTerminalMode(); 91 91 92 92 bool bPrintStatusLine_; 93 93 bool bStatusPrinted_; 94 std::vector< unsigned>statusLineWidths_;95 unsigned intstatusLineMaxWidth_;96 static const unsignedminOutputLines_ = 3;94 std::vector<int> statusLineWidths_; 95 int statusLineMaxWidth_; 96 static const minOutputLines_ = 3; 97 97 termios* originalTerminalSettings_; 98 98 … … 101 101 void moveCursor(int dx, int dy); 102 102 void writeText(const std::string& text, const COORD& pos, WORD attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); 103 void createNewOutputLines( unsignedint lines);103 void createNewOutputLines(int lines); 104 104 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 } 105 111 106 112 DWORD originalTerminalSettings_; … … 108 114 HANDLE stdOutHandle_; 109 115 int inputLineRow_; 110 unsigned intinputLineHeight_;111 const unsigned intstatusLines_;112 unsigned intlastOutputLineHeight_;116 int inputLineHeight_; 117 const int statusLines_; 118 int lastOutputLineHeight_; 113 119 uint64_t lastRefreshTime_; 114 120 #endif
Note: See TracChangeset
for help on using the changeset viewer.