/* client/console.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include #include #include #include "auxiliary/functions.h" #include "audio/audio.h" #include "core/application.h" #include "core/core.h" #include "core/gameinterface.h" #include "filesystem/filesystem.h" #include "render/gl.h" #include "ui/console.h" #include "ui/definitions.h" #include "ui/paint.h" #include "ui/ui.h" namespace ui { const float DEFAULT_CONSOLE_HEIGHT = 0.7f; const size_t DEFAULT_MAX_HISTO_LINES = 512; // the global console buffer object ConsoleBuffer Console::con_buffer; /* -- ConsoleBuffer ------------------------------------------------ */ ConsoleBuffer::ConsoleBuffer() : sys::ConsoleInterface() { //con_print << "^BInitializing console..." << std::endl; } ConsoleBuffer::~ConsoleBuffer() { //con_print << "^BShutting down console..." << std::endl; } //--- Console ----------------------------------------------------- Console::Console(ui::Widget *parent) : ui::Window(parent) { set_visible(false); set_border(false); set_background(true); set_label("console"); history.clear(); history.push_back(""); history_pos = history.rbegin(); std::string version("^F" + core::name() + ' ' + core::version()); console_versionlabel = new Label(this, version.c_str()); console_versionlabel->set_border(false); console_versionlabel->set_background(false); console_scrollpane = new ScrollPane(this, con_buffer.log()); console_scrollpane->set_border(false); console_scrollpane->set_background(false); console_scrollpane->set_scroll(0); console_scrollbar = new ScrollBar(this); console_scrollbar->set_border(false); console_scrollbar->set_background(false); console_input = new InputBox(this); console_input->set_focus(); console_input->set_border(false); console_input->set_background(false); console_input->set_prompt("^N>"); load_history(); } Console::~Console() { save_history(); history.clear(); } void Console::show() { ui::Window::show(); raise(); SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_ShowCursor(SDL_ENABLE); console_scrollpane->set_scroll(0); console_scrollpane->set_offset(3); history_pos = history.rbegin(); (*history_pos).clear(); console_input->set_text((*history_pos)); console_input->set_focus(); audio::play("ui/console"); } void Console::hide() { ui::Window::hide(); core::Cvar *input_grab = core::Cvar::find("input_grab"); if (!input_grab || input_grab->value()) { SDL_WM_GrabInput(SDL_GRAB_ON); SDL_ShowCursor(SDL_DISABLE); } else { SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_ShowCursor(SDL_ENABLE); } audio::play("ui/console"); } void Console::toggle() { if (visible()) hide(); else show(); } bool Console::on_emit(Widget *sender, const Event event, void *data) { if (sender == console_scrollbar) { if (event == ui::Widget::EventScrollBarChanged) { console_scrollpane->set_scroll( (con_buffer.log().size() - console_scrollbar->value()) ); return true; } } return false; } bool Console::on_keypress(const int key, const unsigned int modifier) { // number of lines to scroll const size_t scroll_offset = 3; ui::Text::reverse_iterator upit; switch (key) { case SDLK_ESCAPE: if (visible()) { hide(); return true; } else { return false; } break; case SDLK_TAB: console_input->complete(); return true; break; case SDLK_RETURN: if (console_input->text().size()) { // store input in history while (history.size() >= DEFAULT_MAX_HISTO_LINES) { history.pop_front(); } core::cmd() << console_input->text() << std::endl; con_print << "^B>" << console_input->text() << std::endl; (*history.rbegin()).assign(console_input->text()); history.push_back(""); history_pos = history.rbegin(); console_input->set_text((*history_pos)); } return true; break; case SDLK_UP: upit = history_pos; ++upit; if (upit != history.rend()) { history_pos = upit; console_input->set_text((*history_pos)); } return true; break; case SDLK_DOWN: if (history_pos != history.rbegin()) { --history_pos; console_input->set_text((*history_pos)); } return true; break; case 512 + SDL_BUTTON_WHEELUP: case SDLK_PAGEUP: console_scrollpane->inc_scroll(scroll_offset); return true; break; case 512 + SDL_BUTTON_WHEELDOWN: case SDLK_PAGEDOWN: console_scrollpane->dec_scroll(scroll_offset); return true; break; } return false; } void Console::draw() { console_scrollbar->set_range(0, (float) con_buffer.log().size()); console_scrollbar->set_value( (float) (con_buffer.log().size() - console_scrollpane->scroll())); // disable mouse cursor if (has_mouse_focus()) { ui::root()->set_pointer(); } } void Console::resize() { const float padding = font()->width(); if (core::application()->connected()) { set_size(parent()->size().width(), parent()->size().height() * DEFAULT_CONSOLE_HEIGHT); } else { set_size(parent()->size()); } // resize scrollbar console_scrollbar->set_size( font()->height(), height() ); console_scrollbar->set_location( width() - console_scrollbar->width(), 0.0f ); // resize version label console_versionlabel->set_size( width() - console_scrollbar->width() - padding, font()->height() * 1.5f ); console_versionlabel->set_location( padding, 0.0f ); // resize input bar console_input->set_size( console_versionlabel->width(), font()->height() ); console_input->set_location( console_versionlabel ->left(), bottom() - console_input->height() ); // resize scroll pane console_scrollpane->set_size( console_versionlabel->width(), console_input->top() - console_versionlabel->bottom() ); console_scrollpane->set_location( console_versionlabel->left(), console_versionlabel->bottom() ); } void Console::save_history() { if (history.size() <= 1) return; std::string filename(filesystem::writedir()); filename.append("history.txt"); std::ofstream ofs(filename.c_str()); if (!ofs.is_open()) { con_warn << "Could not write " << filename << std::endl; return; } ui::Text::iterator it; size_t l = 1; for (it = history.begin(); it != history.end(); it++) { if (l < history.size()) ofs << (*it) << std::endl; l++; } ofs.close(); } void Console::load_history() { std::string filename(filesystem::writedir()); filename.append("history.txt"); std::ifstream ifs(filename.c_str(), std::ifstream::in); if (!ifs.is_open()) { con_warn << "Could not read " << filename << std::endl; return; } history.clear(); char line[MAXCMDSIZE]; while (ifs.getline(line, MAXCMDSIZE - 1)) { history.push_back(line); } ifs.close(); history.push_back(""); history_pos = history.rbegin(); } }