Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/console/src/libraries/core/IOConsole.cc @ 5970

Last change on this file since 5970 was 5970, checked in by rgrieder, 15 years ago

And what the hell ever happened here.
Adding missing file.

File size: 9.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Oliver Scheuss
24 *      Reto Grieder
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "IOConsole.h"
31
32#include <cstring>
33#include <iomanip>
34#include <iostream>
35
36#include "util/Clock.h"
37#include "util/Debug.h"
38#include "util/Sleep.h"
39#include "core/CommandExecutor.h"
40#include "core/Game.h"
41#include "core/GameMode.h"
42#include "core/Shell.h"
43#include "core/input/InputBuffer.h"
44
45#ifdef ORXONOX_PLATFORM_UNIX
46#include <termios.h>
47#endif
48
49namespace orxonox
50{
51    IOConsole* IOConsole::singletonPtr_s = NULL;
52
53#ifdef ORXONOX_PLATFORM_UNIX
54
55    termios* IOConsole::originalTerminalSettings_;
56
57    IOConsole::IOConsole()
58        : shell_(Shell::getInstance())
59        , cleanLine_(true)
60        , bEscapeMode_(false)
61        , buffer_(Shell::getInstance().getInputBuffer())
62        , inputIterator_(0)
63        , cursorX_(0)
64        , cursorY_(0)
65    {
66        this->originalTerminalSettings_ = new termios;
67        this->setTerminalMode();
68    }
69
70    IOConsole::~IOConsole()
71    {
72        std::cout << "\033[0G\033[K";
73        std::cout.flush();
74        resetTerminalMode();
75        delete this->originalTerminalSettings_;
76        COUT(0) << "Press enter to end the game..." << std::endl;
77    }
78
79    void IOConsole::setTerminalMode()
80    {
81        termios new_settings;
82
83        tcgetattr(0,this->originalTerminalSettings_);
84        new_settings = *this->originalTerminalSettings_;
85        new_settings.c_lflag &= ~( ICANON | ECHO );
86        //         new_settings.c_lflag |= ( ISIG | IEXTEN );
87        new_settings.c_cc[VTIME] = 1;
88        new_settings.c_cc[VMIN] = 0;
89        tcsetattr(0,TCSANOW,&new_settings);
90        COUT(0) << endl;
91        //       atexit(&IOConsole::resetTerminalMode);
92    }
93
94    void IOConsole::resetTerminalMode()
95    {
96        tcsetattr(0, TCSANOW, IOConsole::originalTerminalSettings_);
97    }
98
99    void IOConsole::update(const Clock& time)
100    {
101        unsigned c;
102        while (read(STDIN_FILENO, &c, 1) == 1)
103        {
104            if (this->bEscapeMode_)
105            {
106                this->escapeSequence_ += c;
107                bool clear = true;
108                if      (this->escapeSequence_ == "\033")
109                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape,   0, 0));
110                else if (this->escapeSequence_ == "[A")
111                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Up,       0, 0));
112                else if (this->escapeSequence_ == "[B")
113                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Down,     0, 0));
114                else if (this->escapeSequence_ == "[C")
115                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Right,    0, 0));
116                else if (this->escapeSequence_ == "[D")
117                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Left,     0, 0));
118                else if (this->escapeSequence_ == "[1~")
119                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Home,     0, 0));
120                else if (this->escapeSequence_ == "[2~")
121                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert,   0, 0));
122                else if (this->escapeSequence_ == "[4~")
123                    this->buffer_->buttonPressed(KeyEvent(KeyCode::End,      0, 0));
124                else if (this->escapeSequence_ == "[5~")
125                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp,   0, 0));
126                else if (this->escapeSequence_ == "[6~")
127                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, 0, 0));
128                // Get Alt+Tab combination when switching applications
129                else if (this->escapeSequence_ == "\t")
130                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, '\t', KeyboardModifier::Alt));
131                else if (this->escapeSequence_.size() > 4)
132                    clear = true; // Something went wrong, start over
133                else
134                    clear = false;
135
136                if (clear)
137                    this->escapeSequence_.clear();
138            }
139            else // not in an escape sequence
140            {
141                if (c == '\033')
142                    this->bEscapeMode_ = true;
143                else
144                {
145                    KeyCode::ByEnum code;
146                    switch (c)
147                    {
148                    case '\n': code = KeyCode::Return; break;
149                    case  127: code = KeyCode::Delete; break; 
150                    case '\b': code = KeyCode::Back;   break;
151                    case '\t': code = KeyCode::Tab;    break;
152                    default:
153                        // We don't encode the key code (would be a very large switch)
154                        // because the InputBuffer will only insert the text anyway
155                        // Replacement character is simply KeyCode::A
156                        code = KeyCode::A;
157                    }
158                    this->buffer_->buttonPressed(KeyEvent(code, c, 0));
159                }
160            }
161        }
162    }
163
164    void IOConsole::printOutputLine(const std::string& line)
165    {
166        // Save cursor position
167        std::cout << "\033[s";
168
169        std::string output;
170
171        // Handle line colouring by inspecting the first letter
172        char level = 0;
173        if (!line.empty())
174            level = line[0];
175        if (level >= -1 && level <= 6)
176            output = line.substr(1);
177        else
178            output = line;
179
180        // Colour line
181        switch (level)
182        {
183        case -1: std::cout << "\033[30m"; break;
184        case  1: std::cout << "\033[91m"; break;
185        case  2: std::cout << "\033[31m"; break;
186        case  3: std::cout << "\033[34m"; break;
187        case  4: std::cout << "\033[36m"; break;
188        case  5: std::cout << "\033[35m"; break;
189        case  6: std::cout << "\033[37m"; break;
190        default:
191        }
192
193        // Print output line
194        std::cout << output << std::endl;
195
196        // Reset colour to black
197        std::cout << "\033[30m";
198        // Restore cursor position
199        std::cout << "\033[u";
200        std::cout.flush();
201    }
202
203    void IOConsole::printInputLine()
204    {
205        // set cursor to the beginning of the line and erase the line
206        std::cout << "\033[0G\033[K";
207        // print status line
208        std::cout << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, " << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms avg ticktime # ";
209        // save cursor position
210        std::cout << "\033[s";
211        // print commandLine buffer
212        std::cout << this->shell_.getInput();
213        // restore cursor position and move it cursorX_ to the right
214        std::cout << "\033[u";
215        if (this->buffer_->getCursorPosition() > 0)
216            std::cout << "\033[" << this->buffer_->getCursorPosition() << "C";
217        std::cout.flush();
218    }
219
220#endif /* ORXONOX_PLATFORM_UNIX */
221
222    // ###############################
223    // ###  ShellListener methods  ###
224    // ###############################
225
226    /**
227    @brief
228        Called if all output-lines have to be redrawn.
229    */
230    void IOConsole::linesChanged()
231    {
232        // Method only gets called upon start to draw all the lines
233        // But we are using std::cout anyway, so do nothing here
234    }
235
236    /**
237    @brief
238        Called if only the last output-line has changed.
239    */
240    void IOConsole::onlyLastLineChanged()
241    {
242        // We cannot do anything here because printed lines are fixed
243        COUT(2) << "Warning: Trying to edit last console lines, which is impossible!" << std::endl;
244    }
245
246    /**
247    @brief
248        Called if a new output-line was added.
249    */
250    void IOConsole::lineAdded()
251    {
252        this->printOutputLine(*(this->shell_.getNewestLineIterator()));
253    }
254
255    /**
256    @brief
257        Called if the text in the input-line has changed.
258    */
259    void IOConsole::inputChanged()
260    {
261        this->printInputLine();
262    }
263
264    /**
265    @brief
266        Called if the position of the cursor in the input-line has changed.
267    */
268    void IOConsole::cursorChanged()
269    {
270        this->printInputLine();
271    }
272
273    /**
274    @brief
275        Called if the console gets closed.
276    */
277    void InGameConsole::exit()
278    {
279        // Exit is not an option, IOConsole always exists
280    }
281
282}
Note: See TracBrowser for help on using the repository browser.