2010-07-21 08:08:38 +00:00
|
|
|
#include "console.hpp"
|
|
|
|
|
2015-01-10 01:50:43 +00:00
|
|
|
#include <MyGUI_EditBox.h>
|
2019-05-17 15:09:40 +00:00
|
|
|
#include <MyGUI_InputManager.h>
|
2019-05-16 06:28:56 +00:00
|
|
|
#include <MyGUI_LayerManager.h>
|
2015-01-10 01:50:43 +00:00
|
|
|
|
2014-01-19 07:34:54 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
#include <boost/filesystem/fstream.hpp>
|
|
|
|
|
2019-12-07 08:11:45 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
|
|
|
Include additional headers for multiplayer purposes
|
|
|
|
*/
|
|
|
|
#include <components/openmw-mp/TimedLog.hpp>
|
|
|
|
#include "../mwmp/Main.hpp"
|
|
|
|
#include "../mwmp/Networking.hpp"
|
|
|
|
#include "../mwmp/LocalPlayer.hpp"
|
|
|
|
#include "../mwmp/ObjectList.hpp"
|
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
#include <components/compiler/exception.hpp>
|
2013-08-07 17:16:20 +00:00
|
|
|
#include <components/compiler/extensions0.hpp>
|
2021-05-15 20:15:46 +00:00
|
|
|
#include <components/compiler/lineparser.hpp>
|
|
|
|
#include <components/compiler/scanner.hpp>
|
|
|
|
#include <components/compiler/locals.hpp>
|
|
|
|
#include <components/interpreter/interpreter.hpp>
|
2010-07-21 08:08:38 +00:00
|
|
|
|
|
|
|
#include "../mwscript/extensions.hpp"
|
|
|
|
|
2012-04-23 13:27:03 +00:00
|
|
|
#include "../mwbase/environment.hpp"
|
2019-03-10 14:05:56 +00:00
|
|
|
#include "../mwbase/scriptmanager.hpp"
|
2013-06-16 16:06:55 +00:00
|
|
|
#include "../mwbase/windowmanager.hpp"
|
2014-12-19 10:26:54 +00:00
|
|
|
#include "../mwbase/world.hpp"
|
2012-04-23 13:27:03 +00:00
|
|
|
|
2014-02-23 19:11:05 +00:00
|
|
|
#include "../mwworld/esmstore.hpp"
|
2019-03-10 14:05:56 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
2014-02-23 19:11:05 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
namespace MWGui
|
|
|
|
{
|
|
|
|
class ConsoleInterpreterContext : public MWScript::InterpreterContext
|
|
|
|
{
|
|
|
|
Console& mConsole;
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
public:
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2012-04-23 13:27:03 +00:00
|
|
|
ConsoleInterpreterContext (Console& console, MWWorld::Ptr reference);
|
2011-04-26 19:48:13 +00:00
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void report (const std::string& message) override;
|
2010-07-21 08:08:38 +00:00
|
|
|
};
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console,
|
2012-04-23 13:27:03 +00:00
|
|
|
MWWorld::Ptr reference)
|
|
|
|
: MWScript::InterpreterContext (
|
2020-11-13 07:39:47 +00:00
|
|
|
reference.isEmpty() ? nullptr : &reference.getRefData().getLocals(), reference),
|
2010-07-21 08:08:38 +00:00
|
|
|
mConsole (console)
|
|
|
|
{}
|
|
|
|
|
2011-04-26 19:48:13 +00:00
|
|
|
void ConsoleInterpreterContext::report (const std::string& message)
|
|
|
|
{
|
|
|
|
mConsole.printOK (message);
|
|
|
|
}
|
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
bool Console::compile (const std::string& cmd, Compiler::Output& output)
|
|
|
|
{
|
|
|
|
try
|
2010-08-22 09:14:14 +00:00
|
|
|
{
|
2010-07-21 11:34:52 +00:00
|
|
|
ErrorHandler::reset();
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
std::istringstream input (cmd + '\n');
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions());
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
Compiler::LineParser parser (*this, mCompilerContext, output.getLocals(),
|
2010-07-21 11:34:52 +00:00
|
|
|
output.getLiterals(), output.getCode(), true);
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
scanner.scan (parser);
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
return isGood();
|
|
|
|
}
|
2012-03-15 15:01:41 +00:00
|
|
|
catch (const Compiler::SourceException&)
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
|
|
|
// error has already been reported via error handler
|
|
|
|
}
|
|
|
|
catch (const std::exception& error)
|
|
|
|
{
|
2014-05-28 20:32:26 +00:00
|
|
|
printError (std::string ("Error: ") + error.what());
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Console::report (const std::string& message, const Compiler::TokenLoc& loc, Type type)
|
|
|
|
{
|
|
|
|
std::ostringstream error;
|
|
|
|
error << "column " << loc.mColumn << " (" << loc.mLiteral << "):";
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
printError (error.str());
|
|
|
|
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Console::report (const std::string& message, Type type)
|
|
|
|
{
|
|
|
|
printError ((type==ErrorMessage ? "error: " : "warning: ") + message);
|
|
|
|
}
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2011-01-12 17:24:00 +00:00
|
|
|
void Console::listNames()
|
|
|
|
{
|
|
|
|
if (mNames.empty())
|
|
|
|
{
|
2011-01-12 17:48:37 +00:00
|
|
|
// keywords
|
2011-01-12 17:24:00 +00:00
|
|
|
std::istringstream input ("");
|
|
|
|
|
|
|
|
Compiler::Scanner scanner (*this, input, mCompilerContext.getExtensions());
|
|
|
|
|
|
|
|
scanner.listKeywords (mNames);
|
|
|
|
|
2011-01-12 17:48:37 +00:00
|
|
|
// identifier
|
2012-11-05 20:34:11 +00:00
|
|
|
const MWWorld::ESMStore& store =
|
|
|
|
MWBase::Environment::get().getWorld()->getStore();
|
2011-01-12 17:48:37 +00:00
|
|
|
|
2012-11-05 20:34:11 +00:00
|
|
|
for (MWWorld::ESMStore::iterator it = store.begin(); it != store.end(); ++it)
|
2011-01-12 17:48:37 +00:00
|
|
|
{
|
2012-11-06 09:14:03 +00:00
|
|
|
it->second->listIdentifier (mNames);
|
2011-01-12 17:48:37 +00:00
|
|
|
}
|
|
|
|
|
2015-01-06 00:10:09 +00:00
|
|
|
// exterior cell names aren't technically identifiers, but since the COC function accepts them,
|
|
|
|
// we should list them too
|
|
|
|
for (MWWorld::Store<ESM::Cell>::iterator it = store.get<ESM::Cell>().extBegin();
|
|
|
|
it != store.get<ESM::Cell>().extEnd(); ++it)
|
|
|
|
{
|
|
|
|
if (!it->mName.empty())
|
|
|
|
mNames.push_back(it->mName);
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:48:37 +00:00
|
|
|
// sort
|
2011-01-12 17:24:00 +00:00
|
|
|
std::sort (mNames.begin(), mNames.end());
|
2015-01-06 00:10:09 +00:00
|
|
|
|
|
|
|
// remove duplicates
|
|
|
|
mNames.erase( std::unique( mNames.begin(), mNames.end() ), mNames.end() );
|
2011-01-12 17:24:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 09:43:28 +00:00
|
|
|
Console::Console(int w, int h, bool consoleOnlyScripts)
|
2013-07-14 21:54:28 +00:00
|
|
|
: WindowBase("openmw_console.layout"),
|
2012-07-30 09:43:28 +00:00
|
|
|
mCompilerContext (MWScript::CompilerContext::Type_Console),
|
|
|
|
mConsoleOnlyScripts (consoleOnlyScripts)
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
|
|
|
setCoord(10,10, w-10, h/2);
|
|
|
|
|
2013-07-14 21:54:28 +00:00
|
|
|
getWidget(mCommandLine, "edit_Command");
|
|
|
|
getWidget(mHistory, "list_History");
|
2010-07-21 08:08:38 +00:00
|
|
|
|
|
|
|
// Set up the command line box
|
2013-07-14 21:54:28 +00:00
|
|
|
mCommandLine->eventEditSelectAccept +=
|
2010-07-21 08:08:38 +00:00
|
|
|
newDelegate(this, &Console::acceptCommand);
|
2013-07-14 21:54:28 +00:00
|
|
|
mCommandLine->eventKeyButtonPressed +=
|
2010-07-21 08:08:38 +00:00
|
|
|
newDelegate(this, &Console::keyPress);
|
|
|
|
|
|
|
|
// Set up the log window
|
2013-07-14 21:54:28 +00:00
|
|
|
mHistory->setOverflowToTheLeft(true);
|
2010-08-22 09:14:14 +00:00
|
|
|
|
2010-07-21 08:08:38 +00:00
|
|
|
// compiler
|
2013-08-07 00:38:41 +00:00
|
|
|
Compiler::registerExtensions (mExtensions, mConsoleOnlyScripts);
|
2012-07-30 09:43:28 +00:00
|
|
|
mCompilerContext.setExtensions (&mExtensions);
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 15:10:53 +00:00
|
|
|
void Console::onOpen()
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
|
|
|
// Give keyboard focus to the combo box whenever the console is
|
2019-05-16 06:28:56 +00:00
|
|
|
// turned on and place it over other widgets
|
2019-06-08 23:08:09 +00:00
|
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
2019-05-16 06:28:56 +00:00
|
|
|
MyGUI::LayerManager::getInstance().upLayerItem(mMainWidget);
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
|
2015-09-26 00:08:23 +00:00
|
|
|
void Console::print(const std::string &msg, const std::string& color)
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
2015-09-26 00:08:23 +00:00
|
|
|
mHistory->addText(color + MyGUI::TextIterator::toTagsString(msg));
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Console::printOK(const std::string &msg)
|
|
|
|
{
|
2015-09-26 00:08:23 +00:00
|
|
|
print(msg + "\n", "#FF00FF");
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Console::printError(const std::string &msg)
|
|
|
|
{
|
2015-09-26 00:08:23 +00:00
|
|
|
print(msg + "\n", "#FF2222");
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
|
2012-07-30 09:57:19 +00:00
|
|
|
void Console::execute (const std::string& command)
|
|
|
|
{
|
|
|
|
// Log the command
|
2015-09-26 00:08:23 +00:00
|
|
|
print("> " + command + "\n");
|
2012-07-30 09:57:19 +00:00
|
|
|
|
|
|
|
Compiler::Locals locals;
|
2019-03-10 14:05:56 +00:00
|
|
|
if (!mPtr.isEmpty())
|
|
|
|
{
|
|
|
|
std::string script = mPtr.getClass().getScript(mPtr);
|
|
|
|
if (!script.empty())
|
|
|
|
locals = MWBase::Environment::get().getScriptManager()->getLocals(script);
|
|
|
|
}
|
2012-07-30 09:57:19 +00:00
|
|
|
Compiler::Output output (locals);
|
|
|
|
|
|
|
|
if (compile (command + "\n", output))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
ConsoleInterpreterContext interpreterContext (*this, mPtr);
|
2018-07-22 21:46:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
2019-12-07 08:11:45 +00:00
|
|
|
Send an ID_CONSOLE_COMMAND packet to the server with the
|
|
|
|
command and target used
|
|
|
|
|
2018-07-22 21:46:07 +00:00
|
|
|
Mark this InterpreterContext as having a CONSOLE context,
|
|
|
|
so that packets sent by the Interpreter can have their
|
|
|
|
origin determined by serverside scripts
|
|
|
|
*/
|
2020-07-26 18:03:33 +00:00
|
|
|
interpreterContext.trackContextType(Interpreter::Context::CONSOLE);
|
2019-12-07 08:11:45 +00:00
|
|
|
|
|
|
|
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
|
|
objectList->reset();
|
|
|
|
objectList->packetOrigin = mwmp::CLIENT_CONSOLE;
|
|
|
|
objectList->consoleCommand = command;
|
|
|
|
|
|
|
|
if (mPtr.isEmpty())
|
|
|
|
objectList->cell = mwmp::Main::get().getLocalPlayer()->cell;
|
|
|
|
else
|
|
|
|
{
|
2020-02-15 08:24:05 +00:00
|
|
|
objectList->addObjectGeneric(mPtr);
|
2019-12-07 08:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
objectList->sendConsoleCommand();
|
2018-07-22 21:46:07 +00:00
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
|
|
|
|
2012-07-30 09:57:19 +00:00
|
|
|
Interpreter::Interpreter interpreter;
|
|
|
|
MWScript::installOpcodes (interpreter, mConsoleOnlyScripts);
|
|
|
|
std::vector<Interpreter::Type_Code> code;
|
|
|
|
output.getCode (code);
|
|
|
|
interpreter.run (&code[0], code.size(), interpreterContext);
|
|
|
|
}
|
|
|
|
catch (const std::exception& error)
|
|
|
|
{
|
2014-05-28 20:32:26 +00:00
|
|
|
printError (std::string ("Error: ") + error.what());
|
2012-07-30 09:57:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 10:37:46 +00:00
|
|
|
void Console::executeFile (const std::string& path)
|
|
|
|
{
|
2014-01-19 07:34:54 +00:00
|
|
|
namespace bfs = boost::filesystem;
|
2014-01-19 14:13:35 +00:00
|
|
|
bfs::ifstream stream ((bfs::path(path)));
|
2012-07-30 10:37:46 +00:00
|
|
|
|
|
|
|
if (!stream.is_open())
|
|
|
|
printError ("failed to open file: " + path);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
|
|
|
|
while (std::getline (stream, line))
|
|
|
|
execute (line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-30 14:57:07 +00:00
|
|
|
void Console::clear()
|
|
|
|
{
|
|
|
|
resetReference();
|
|
|
|
}
|
|
|
|
|
2019-06-07 16:41:35 +00:00
|
|
|
bool isWhitespace(char c)
|
|
|
|
{
|
|
|
|
return c == ' ' || c == '\t';
|
|
|
|
}
|
|
|
|
|
2013-03-03 12:11:02 +00:00
|
|
|
void Console::keyPress(MyGUI::Widget* _sender,
|
2010-07-21 08:08:38 +00:00
|
|
|
MyGUI::KeyCode key,
|
|
|
|
MyGUI::Char _char)
|
|
|
|
{
|
2019-06-06 20:09:45 +00:00
|
|
|
if(MyGUI::InputManager::getInstance().isControlPressed())
|
|
|
|
{
|
|
|
|
if(key == MyGUI::KeyCode::W)
|
|
|
|
{
|
2019-06-07 16:41:35 +00:00
|
|
|
const auto& caption = mCommandLine->getCaption();
|
|
|
|
if(caption.empty())
|
2019-06-06 20:09:45 +00:00
|
|
|
return;
|
2019-06-07 16:41:35 +00:00
|
|
|
size_t max = mCommandLine->getTextCursor();
|
|
|
|
while(max > 0 && (isWhitespace(caption[max - 1]) || caption[max - 1] == '>'))
|
2019-06-06 20:09:45 +00:00
|
|
|
max--;
|
2019-06-07 16:41:35 +00:00
|
|
|
while(max > 0 && !isWhitespace(caption[max - 1]) && caption[max - 1] != '>')
|
2019-06-06 20:09:45 +00:00
|
|
|
max--;
|
2019-06-07 16:41:35 +00:00
|
|
|
size_t length = mCommandLine->getTextCursor() - max;
|
|
|
|
if(length > 0)
|
|
|
|
{
|
2021-02-25 18:33:11 +00:00
|
|
|
auto text = caption;
|
2019-06-07 16:41:35 +00:00
|
|
|
text.erase(max, length);
|
|
|
|
mCommandLine->setCaption(text);
|
|
|
|
mCommandLine->setTextCursor(max);
|
|
|
|
}
|
2019-06-06 20:09:45 +00:00
|
|
|
}
|
|
|
|
else if(key == MyGUI::KeyCode::U)
|
|
|
|
{
|
2019-06-07 16:41:35 +00:00
|
|
|
if(mCommandLine->getTextCursor() > 0)
|
|
|
|
{
|
2021-02-25 18:33:11 +00:00
|
|
|
auto text = mCommandLine->getCaption();
|
2019-06-07 16:41:35 +00:00
|
|
|
text.erase(0, mCommandLine->getTextCursor());
|
|
|
|
mCommandLine->setCaption(text);
|
|
|
|
mCommandLine->setTextCursor(0);
|
|
|
|
}
|
|
|
|
}
|
2019-06-06 20:09:45 +00:00
|
|
|
}
|
|
|
|
else if(key == MyGUI::KeyCode::Tab)
|
2011-07-18 16:49:38 +00:00
|
|
|
{
|
|
|
|
std::vector<std::string> matches;
|
|
|
|
listNames();
|
2014-05-02 20:19:02 +00:00
|
|
|
std::string oldCaption = mCommandLine->getCaption();
|
|
|
|
std::string newCaption = complete( mCommandLine->getOnlyText(), matches );
|
|
|
|
mCommandLine->setCaption(newCaption);
|
|
|
|
|
|
|
|
// List candidates if repeatedly pressing tab
|
2016-02-22 18:06:12 +00:00
|
|
|
if (oldCaption == newCaption && !matches.empty())
|
2011-07-18 16:49:38 +00:00
|
|
|
{
|
2014-05-02 20:19:02 +00:00
|
|
|
int i = 0;
|
|
|
|
printOK("");
|
2019-03-02 09:27:59 +00:00
|
|
|
for(std::string& match : matches)
|
2014-05-02 20:19:02 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
if(i == 50)
|
2014-05-02 20:19:02 +00:00
|
|
|
break;
|
2019-03-02 09:27:59 +00:00
|
|
|
|
|
|
|
printOK(match);
|
|
|
|
i++;
|
2014-05-02 20:19:02 +00:00
|
|
|
}
|
2011-07-18 16:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-14 21:54:28 +00:00
|
|
|
if(mCommandHistory.empty()) return;
|
2010-07-21 08:08:38 +00:00
|
|
|
|
|
|
|
// Traverse history with up and down arrows
|
|
|
|
if(key == MyGUI::KeyCode::ArrowUp)
|
|
|
|
{
|
|
|
|
// If the user was editing a string, store it for later
|
2013-07-14 21:54:28 +00:00
|
|
|
if(mCurrent == mCommandHistory.end())
|
2014-01-04 04:24:32 +00:00
|
|
|
mEditString = mCommandLine->getOnlyText();
|
2010-07-21 08:08:38 +00:00
|
|
|
|
2013-07-14 21:54:28 +00:00
|
|
|
if(mCurrent != mCommandHistory.begin())
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
2013-07-31 16:46:32 +00:00
|
|
|
--mCurrent;
|
2013-07-14 21:54:28 +00:00
|
|
|
mCommandLine->setCaption(*mCurrent);
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(key == MyGUI::KeyCode::ArrowDown)
|
|
|
|
{
|
2013-07-14 21:54:28 +00:00
|
|
|
if(mCurrent != mCommandHistory.end())
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
2013-11-23 21:48:39 +00:00
|
|
|
++mCurrent;
|
2010-07-21 08:08:38 +00:00
|
|
|
|
2013-07-14 21:54:28 +00:00
|
|
|
if(mCurrent != mCommandHistory.end())
|
|
|
|
mCommandLine->setCaption(*mCurrent);
|
2010-07-21 08:08:38 +00:00
|
|
|
else
|
|
|
|
// Restore the edit string
|
2013-07-14 21:54:28 +00:00
|
|
|
mCommandLine->setCaption(mEditString);
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-03 12:11:02 +00:00
|
|
|
void Console::acceptCommand(MyGUI::EditBox* _sender)
|
2010-07-21 08:08:38 +00:00
|
|
|
{
|
2014-01-04 04:24:32 +00:00
|
|
|
const std::string &cm = mCommandLine->getOnlyText();
|
2010-07-21 08:08:38 +00:00
|
|
|
if(cm.empty()) return;
|
|
|
|
|
|
|
|
// Add the command to the history, and set the current pointer to
|
|
|
|
// the end of the list
|
2015-01-27 01:08:09 +00:00
|
|
|
if (mCommandHistory.empty() || mCommandHistory.back() != cm)
|
|
|
|
mCommandHistory.push_back(cm);
|
2013-07-14 21:54:28 +00:00
|
|
|
mCurrent = mCommandHistory.end();
|
|
|
|
mEditString.clear();
|
2015-06-05 19:44:06 +00:00
|
|
|
|
|
|
|
// Reset the command line before the command execution.
|
2015-06-05 19:57:35 +00:00
|
|
|
// It prevents the re-triggering of the acceptCommand() event for the same command
|
|
|
|
// during the actual command execution
|
2015-06-05 19:00:02 +00:00
|
|
|
mCommandLine->setCaption("");
|
2010-07-21 08:08:38 +00:00
|
|
|
|
2012-07-30 09:57:19 +00:00
|
|
|
execute (cm);
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|
2011-07-18 16:49:38 +00:00
|
|
|
|
|
|
|
std::string Console::complete( std::string input, std::vector<std::string> &matches )
|
|
|
|
{
|
2013-04-17 22:56:48 +00:00
|
|
|
std::string output = input;
|
|
|
|
std::string tmp = input;
|
2011-07-19 16:42:34 +00:00
|
|
|
bool has_front_quote = false;
|
2011-07-18 16:49:38 +00:00
|
|
|
|
|
|
|
/* Does the input string contain things that don't have to be completed? If yes erase them. */
|
2018-08-02 06:49:53 +00:00
|
|
|
|
|
|
|
/* Erase a possible call to an explicit reference. */
|
|
|
|
size_t explicitPos = tmp.find("->");
|
|
|
|
if (explicitPos != std::string::npos)
|
|
|
|
{
|
|
|
|
tmp.erase(0, explicitPos+2);
|
|
|
|
}
|
|
|
|
|
2011-07-19 16:42:34 +00:00
|
|
|
/* Are there quotation marks? */
|
2013-04-17 22:56:48 +00:00
|
|
|
if( tmp.find('"') != std::string::npos ) {
|
2011-07-19 16:42:34 +00:00
|
|
|
int numquotes=0;
|
2013-04-17 22:56:48 +00:00
|
|
|
for(std::string::iterator it=tmp.begin(); it < tmp.end(); ++it) {
|
2011-07-19 16:42:34 +00:00
|
|
|
if( *it == '"' )
|
|
|
|
numquotes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Is it terminated?*/
|
|
|
|
if( numquotes % 2 ) {
|
|
|
|
tmp.erase( 0, tmp.rfind('"')+1 );
|
|
|
|
has_front_quote = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
size_t pos;
|
2013-04-17 22:56:48 +00:00
|
|
|
if( ( ((pos = tmp.rfind(' ')) != std::string::npos ) ) && ( pos > tmp.rfind('"') ) ) {
|
2011-07-19 16:42:34 +00:00
|
|
|
tmp.erase( 0, tmp.rfind(' ')+1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tmp.clear();
|
|
|
|
}
|
|
|
|
has_front_quote = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* No quotation marks. Are there spaces?*/
|
|
|
|
else {
|
|
|
|
size_t rpos;
|
2013-04-17 22:56:48 +00:00
|
|
|
if( (rpos=tmp.rfind(' ')) != std::string::npos ) {
|
2011-07-19 16:42:34 +00:00
|
|
|
if( rpos == 0 ) {
|
2011-07-18 16:49:38 +00:00
|
|
|
tmp.clear();
|
|
|
|
}
|
2011-07-19 16:42:34 +00:00
|
|
|
else {
|
|
|
|
tmp.erase(0, rpos+1);
|
|
|
|
}
|
2011-07-18 16:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-02 00:16:33 +00:00
|
|
|
|
2011-07-18 16:49:38 +00:00
|
|
|
/* Erase the input from the output string so we can easily append the completed form later. */
|
|
|
|
output.erase(output.end()-tmp.length(), output.end());
|
|
|
|
|
|
|
|
/* Is there still something in the input string? If not just display all commands and return the unchanged input. */
|
|
|
|
if( tmp.length() == 0 ) {
|
|
|
|
matches=mNames;
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Iterate through the vector. */
|
2019-03-02 09:27:59 +00:00
|
|
|
for(std::string& name : mNames)
|
|
|
|
{
|
2011-07-18 16:49:38 +00:00
|
|
|
bool string_different=false;
|
|
|
|
|
|
|
|
/* Is the string shorter than the input string? If yes skip it. */
|
2019-03-02 09:27:59 +00:00
|
|
|
if(name.length() < tmp.length())
|
2011-07-18 16:49:38 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Is the beginning of the string different from the input string? If yes skip it. */
|
2019-03-02 09:27:59 +00:00
|
|
|
for( std::string::iterator iter=tmp.begin(), iter2=name.begin(); iter < tmp.end();++iter, ++iter2) {
|
2015-12-07 20:58:30 +00:00
|
|
|
if( Misc::StringUtils::toLower(*iter) != Misc::StringUtils::toLower(*iter2) ) {
|
2011-07-18 16:49:38 +00:00
|
|
|
string_different=true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( string_different )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* The beginning of the string matches the input string, save it for the next test. */
|
2019-03-02 09:27:59 +00:00
|
|
|
matches.push_back(name);
|
2011-07-18 16:49:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* There are no matches. Return the unchanged input. */
|
|
|
|
if( matches.empty() )
|
|
|
|
{
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Only one match. We're done. */
|
|
|
|
if( matches.size() == 1 ) {
|
2011-07-19 16:42:34 +00:00
|
|
|
/* Adding quotation marks when the input string started with a quotation mark or has spaces in it*/
|
2013-04-17 22:56:48 +00:00
|
|
|
if( ( matches.front().find(' ') != std::string::npos ) ) {
|
2011-07-19 16:42:34 +00:00
|
|
|
if( !has_front_quote )
|
2013-04-17 22:56:48 +00:00
|
|
|
output.append(std::string("\""));
|
|
|
|
return output.append(matches.front() + std::string("\" "));
|
2011-07-19 16:42:34 +00:00
|
|
|
}
|
|
|
|
else if( has_front_quote ) {
|
2013-04-17 22:56:48 +00:00
|
|
|
return output.append(matches.front() + std::string("\" "));
|
2011-07-19 16:42:34 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-04-17 22:56:48 +00:00
|
|
|
return output.append(matches.front() + std::string(" "));
|
2011-07-19 16:42:34 +00:00
|
|
|
}
|
2011-07-18 16:49:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if all matching strings match further than input. If yes complete to this match. */
|
|
|
|
int i = tmp.length();
|
|
|
|
|
2019-03-02 09:27:59 +00:00
|
|
|
for(std::string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); ++iter, ++i)
|
|
|
|
{
|
|
|
|
for(std::string& match : matches)
|
|
|
|
{
|
|
|
|
if(Misc::StringUtils::toLower(match[i]) != Misc::StringUtils::toLower(*iter))
|
|
|
|
{
|
2011-07-18 16:49:38 +00:00
|
|
|
/* Append the longest match to the end of the output string*/
|
2019-03-02 09:27:59 +00:00
|
|
|
output.append(matches.front().substr(0, i));
|
2011-07-19 16:42:34 +00:00
|
|
|
return output;
|
2012-03-15 15:01:41 +00:00
|
|
|
}
|
2011-07-18 16:49:38 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-19 16:42:34 +00:00
|
|
|
|
2011-07-18 16:49:38 +00:00
|
|
|
/* All keywords match with the shortest. Append it to the output string and return it. */
|
|
|
|
return output.append(matches.front());
|
|
|
|
}
|
2012-05-28 07:19:25 +00:00
|
|
|
|
|
|
|
void Console::onResChange(int width, int height)
|
|
|
|
{
|
|
|
|
setCoord(10,10, width-10, height/2);
|
|
|
|
}
|
2012-06-02 10:25:24 +00:00
|
|
|
|
2020-07-11 13:24:20 +00:00
|
|
|
void Console::updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr)
|
|
|
|
{
|
|
|
|
if (mPtr == currentPtr)
|
|
|
|
mPtr = newPtr;
|
|
|
|
}
|
|
|
|
|
2017-09-25 19:03:52 +00:00
|
|
|
void Console::setSelectedObject(const MWWorld::Ptr& object)
|
2012-06-02 10:25:24 +00:00
|
|
|
{
|
2013-04-29 19:19:13 +00:00
|
|
|
if (!object.isEmpty())
|
|
|
|
{
|
|
|
|
if (object == mPtr)
|
|
|
|
{
|
|
|
|
setTitle("#{sConsoleTitle}");
|
|
|
|
mPtr=MWWorld::Ptr();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-10 21:46:24 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp change (major)
|
|
|
|
|
2018-07-13 01:12:03 +00:00
|
|
|
Display the selected object's refNum and mpNum alongside its refId in the
|
2018-05-10 21:46:24 +00:00
|
|
|
title of the console window, for easier debugging of almost everything
|
|
|
|
*/
|
|
|
|
setTitle("#{sConsoleTitle} (" + object.getCellRef().getRefId() + ", " +
|
2018-07-19 08:57:06 +00:00
|
|
|
std::to_string(object.getCellRef().getRefNum().mIndex) + "-" +
|
2018-05-10 21:46:24 +00:00
|
|
|
std::to_string(object.getCellRef().getMpNum()) + ")");
|
|
|
|
/*
|
|
|
|
End of tes3mp change (major)
|
|
|
|
*/
|
2013-04-29 19:19:13 +00:00
|
|
|
mPtr = object;
|
|
|
|
}
|
2013-12-23 23:29:16 +00:00
|
|
|
// User clicked on an object. Restore focus to the console command line.
|
2019-06-08 23:08:09 +00:00
|
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine);
|
2013-04-29 19:19:13 +00:00
|
|
|
}
|
2012-06-02 12:19:02 +00:00
|
|
|
else
|
2013-04-29 19:19:13 +00:00
|
|
|
{
|
2012-06-02 12:19:02 +00:00
|
|
|
setTitle("#{sConsoleTitle}");
|
2013-04-29 19:19:13 +00:00
|
|
|
mPtr = MWWorld::Ptr();
|
|
|
|
}
|
2012-06-02 10:25:24 +00:00
|
|
|
}
|
|
|
|
|
2017-12-26 13:04:28 +00:00
|
|
|
/*
|
|
|
|
Start of tes3mp addition
|
|
|
|
|
|
|
|
Allow the direct setting of a console's Ptr, without the assumption that an object
|
|
|
|
was clicked and that key focus should be restored to the console window, for console
|
|
|
|
commands executed via server scripts
|
|
|
|
*/
|
|
|
|
void Console::setPtr(const MWWorld::Ptr& object)
|
|
|
|
{
|
|
|
|
mPtr = object;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
End of tes3mp addition
|
|
|
|
*/
|
|
|
|
|
2012-06-02 10:25:24 +00:00
|
|
|
void Console::onReferenceUnavailable()
|
|
|
|
{
|
2017-09-25 19:03:52 +00:00
|
|
|
setSelectedObject(MWWorld::Ptr());
|
2012-06-02 10:25:24 +00:00
|
|
|
}
|
2014-06-12 19:46:23 +00:00
|
|
|
|
|
|
|
void Console::resetReference()
|
|
|
|
{
|
|
|
|
ReferenceInterface::resetReference();
|
2017-09-25 19:03:52 +00:00
|
|
|
setSelectedObject(MWWorld::Ptr());
|
2014-06-12 19:46:23 +00:00
|
|
|
}
|
2010-07-21 08:08:38 +00:00
|
|
|
}
|