/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "ultima/shared/gfx/info.h" #include "ultima/shared/early/game.h" #include "ultima/shared/gfx/text_cursor.h" #include "ultima/shared/core/str.h" namespace Ultima { namespace Shared { #define PROMPT_CHAR '\x1' #define SUGGESTED_CR '\r' BEGIN_MESSAGE_MAP(Info, Shared::Gfx::VisualItem) ON_MESSAGE(InfoMsg) ON_MESSAGE(InfoGetCommandKeypress) ON_MESSAGE(InfoGetKeypress) ON_MESSAGE(InfoGetInput) ON_MESSAGE(KeypressMsg) END_MESSAGE_MAP() Info::Info(TreeItem *parent, const Rect &bounds) : Gfx::VisualItem("Info", bounds, parent), _commandRespondTo(nullptr) { _characterInput = new Gfx::CharacterInput(getGame()); _textInput = new Gfx::TextInput(getGame()); } Info::~Info() { delete _characterInput; delete _textInput; } bool Info::InfoMsg(CInfoMsg *msg) { // Iterate through text, dealing with lines one at a time StringArray lines = String(msg->_text).split("\r\n"); if (!_lines.empty() && msg->_replaceLine) _lines.back() = _lines.back().firstChar(); for (uint idx = 0; idx < lines.size(); ++idx) { if (_lines.empty() || idx > 0) _lines.push_back(" "); _lines.back() += lines[idx]; } // Add newline if necessary if (msg->_newLine) _lines.push_back(" "); setDirty(); // Adding any text hides any visible cursor _commandRespondTo = nullptr; Gfx::TextCursor *textCursor = getGame()->_textCursor; textCursor->setVisible(false); return true; } bool Info::InfoGetCommandKeypress(CInfoGetCommandKeypress *msg) { if (_lines.empty() || _lines.back() != " ") _lines.push_back(""); _lines.back() = PROMPT_CHAR; Gfx::TextCursor *textCursor = getGame()->_textCursor; textCursor->setVisible(true); textCursor->setPosition(Point(8, _bounds.bottom - 8)); _commandRespondTo = msg->_responder; return true; } bool Info::InfoGetKeypress(CInfoGetKeypress *msg) { Game *game = getGame(); Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8); _characterInput->show(pt, game->_textColor, msg->_responder); return true; } bool Info::InfoGetInput(CInfoGetInput *msg) { Game *game = getGame(); Point pt(_bounds.left + _lines.back().size() * 8, _bounds.bottom - 8); _textInput->show(pt, msg->_isNumeric, msg->_maxCharacters, game->_textColor, msg->_responder); return true; } bool Info::KeypressMsg(CKeypressMsg *msg) { // If waiting for a command, dispatch the key to the respond, and hide the cursor if (_commandRespondTo) { TreeItem *target = _commandRespondTo; _commandRespondTo = nullptr; getGame()->_textCursor->setVisible(false); CCharacterInputMsg cMsg(msg->_keyState); cMsg.execute(target); return true; } return true; } void Info::draw() { // Clear the background Gfx::VisualSurface s = getSurface(); s.clear(); // Get the number og lines to display uint lineHeight = s.fontHeight(); uint numLines = (s.h + lineHeight - 1) / lineHeight; // Discard any stored lines beyond the top of the display while (_lines.size() > numLines) _lines.remove_at(0); // Display the lines int x = 0, y = s.h - _lines.size() * lineHeight; for (uint idx = 0; idx < _lines.size(); ++idx, x = 0, y += lineHeight) { // Handle drawing the prompt character at the start of lines if necessary Common::String line = _lines[idx]; if (!line.empty() && line[0] == PROMPT_CHAR) { drawPrompt(s, Point(0, y)); x = 8; line.deleteChar(0); } // Write the remainder of the line s.writeString(line, Point(x, y)); } _isDirty = false; } } // End of namespace Shared } // End of namespace Ultima