/* client/chat.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 "core/core.h" #include "client/chat.h" #include "client/console.h" #include "client/keyboard.h" #include "client/video.h" #include "render/render.h" namespace client { namespace chat { // input history std::deque history; std::deque::reverse_iterator history_pos; size_t input_pos = 0; // chatbox visibility bool chat_visible = false; //--- engine functions -------------------------------------------- void func_con_chat(std::string const &args) { std::istringstream argstream(args); int i; if (argstream >> i) { if (i) chat_visible = true; else chat_visible = false; } else chat_visible = !chat_visible; } //--- public ------------------------------------------------------ void init() { // add engine functions core::Func::add("con_chat", (core::FuncPtr) func_con_chat); history.clear(); history.push_back(""); history_pos = history.rbegin(); input_pos = 0; } void shutdown() { // remove engine functions //core::Func::remove("con_chat"); history.clear(); input_pos = 0; } bool visible() { return chat_visible; } void draw() { using namespace render; if (console::visible() || !visible()) return; size_t width = (size_t) (video::width / Text::fontwidth()) - 7; size_t draw_pos = 0; while (input_pos - draw_pos > width) draw_pos += 2; // draw the chat input float y = video::height * 8.0 / 10.0; Text::draw(4 , y, "^Bsay^F:^B"); Text::draw(4+Text::fontwidth()*5 , y, (*history_pos).substr(draw_pos, width)); // draw cursor if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { std::string cursor("^B_"); Text::draw(4+Text::fontwidth()*(input_pos - draw_pos+5), y, cursor); } } void toggle() { chat_visible = !chat_visible; if (chat_visible) { input_pos = 0; history_pos = history.rbegin(); (*history_pos).clear(); } setkeyboardmode(chat_visible); } void keypressed(int key) { std::deque::reverse_iterator upit; switch( key ) { case SDLK_TAB: core::CommandBuffer::complete( (*history_pos), input_pos); break; case SDLK_RETURN: if ((*history_pos).size()) { // store input into history while (history.size() >= MAXHISTOLINES) { history.pop_front(); } core::cmd() << "say " << (*history_pos) << std::endl; (*history.rbegin()) = (*history_pos); history.push_back(""); history_pos = history.rbegin(); input_pos = 0; } toggle(); break; case SDLK_UP: upit = history_pos; ++upit; if (upit != history.rend()) { history_pos = upit; input_pos = (*history_pos).size(); } break; case SDLK_DOWN: if (history_pos != history.rbegin()) { --history_pos; input_pos = (*history_pos).size(); } break; case SDLK_HOME: input_pos = 0; break; case SDLK_END: input_pos = (*history_pos).size(); break; case SDLK_LEFT: if (input_pos > 0) input_pos--; break; case SDLK_RIGHT: if (input_pos < (*history_pos).size()) input_pos++; break; case SDLK_BACKSPACE: if ((*history_pos).size() && input_pos) { (*history_pos).erase(input_pos-1, 1); input_pos--; } break; default: if ((key >= 32 ) && (key <175)) { if (input_pos == (*history_pos).size()) (*history_pos) += (char)key; else (*history_pos).insert(input_pos, 1, (char)key); input_pos++; } break; } } } }